En supposant que j'ai les éléments suivants:
var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
Quelle est la meilleure façon d'obtenir un tableau de tous les âges distincts, de sorte que j'obtienne un tableau de résultats de:
[17, 35]
Existe-t-il un moyen de structurer alternativement les données ou une meilleure méthode de telle sorte que je n'aurais pas à parcourir chaque tableau en vérifiant la valeur de "age" et en vérifiant par rapport à un autre tableau son existence, et en l'ajoutant sinon?
S'il y avait un moyen, je pourrais simplement retirer les âges distincts sans répéter ...
La manière actuellement inefficace que je voudrais améliorer ... Si cela signifie qu'au lieu de "tableau" étant un tableau d'objets, mais une "carte" d'objets avec une clé unique (c'est-à-dire "1,2,3") qui serait d'accord aussi. Je cherche juste le moyen le plus efficace en termes de performances.
Voici comment je le fais actuellement, mais pour moi, l'itération semble juste minable pour l'efficacité même si cela fonctionne ...
var distinct = []
for (var i = 0; i < array.length; i++)
if (array[i].age not in distinct)
distinct.push(array[i].age)
la source
Set
objet etmap
s sont inutiles. Ce travail ne prend qu'une.reduce()
étape simple .Réponses:
Si c'était PHP, je construirais un tableau avec les clés et le prendrais
array_keys
à la fin, mais JS n'a pas un tel luxe. Essayez plutôt ceci:la source
array_unique
comparerait l'ensemble de l'article, pas seulement l'âge comme demandé ici.flags = {}
c'est mieux queflags = []
age
s'agit d'un nombre relativement petit (<120 sûrement)Si vous utilisez ES6 / ES2015 ou une version ultérieure, vous pouvez le faire de cette façon:
Voici un exemple sur la façon de procéder.
la source
TypeError: (intermediate value).slice is not a function
en utilisant ES6
la source
array.filter((value, index, self) => self.map(x => x.age).indexOf(value.age) == index)
Vous pouvez utiliser une approche de dictionnaire comme celle-ci. Fondamentalement, vous attribuez la valeur que vous souhaitez être distincte comme clé dans le "dictionnaire" (ici, nous utilisons un tableau comme objet pour éviter le mode dictionnaire). Si la clé n'existait pas, vous ajoutez cette valeur comme distincte.
Voici une démo fonctionnelle:
Ce sera O (n) où n est le nombre d'objets dans le tableau et m est le nombre de valeurs uniques. Il n'y a pas de moyen plus rapide que O (n) car vous devez inspecter chaque valeur au moins une fois.
La version précédente de celui-ci utilisait un objet, et pour in. Celles-ci étaient de nature mineure et ont depuis été légèrement mises à jour ci-dessus. Cependant, la raison d'une apparente amélioration des performances entre les deux versions dans le jsperf d'origine était due à la petite taille de l'échantillon de données. Ainsi, la comparaison principale dans la version précédente portait sur la différence entre la carte interne et l'utilisation du filtre par rapport aux recherches en mode dictionnaire.
J'ai mis à jour le code ci-dessus, comme indiqué, cependant, j'ai également mis à jour le jsperf pour regarder à travers 1000 objets au lieu de 3. 3 négligé de nombreux pièges de performances impliqués ( jsperf obsolète ).
Performance
https://jsperf.com/filter-vs-dictionary-more-data Lorsque j'ai exécuté ce dictionnaire, il était 96% plus rapide.
la source
if( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); unique[array[i].age] = 0; }
Voici comment résoudre ce problème en utilisant le nouvel ensemble via ES6 pour Typescript à partir du 25 août 2017
la source
En utilisant les fonctionnalités ES6, vous pourriez faire quelque chose comme:
la source
const uniqueObjects = [ ...new Set( array.map( obj => obj.age) ) ].map( age=> { return array.find(obj => obj.age === age) } )
Je mapperais et supprimerais les doublons:
Edit: Aight! Pas le moyen le plus efficace en termes de performances, mais l'OMI le plus simple et le plus lisible. Si vous vous souciez vraiment de la micro-optimisation ou si vous avez d'énormes quantités de données, une
for
boucle régulière sera plus "efficace".la source
if
s. vous obtiendrez des résultats très différents avec trois millions.Exemple ES6
la source
Pour ceux qui veulent retourner un objet avec toutes les propriétés uniques par clé
la source
Il existe déjà de nombreuses réponses valides, mais je voulais en ajouter une qui utilise uniquement la
reduce()
méthode car elle est propre et simple.Utilisez-le comme ceci:
la source
La
forEach
version de la réponse de @ travis-j (utile sur les navigateurs modernes et le monde Node JS):34% plus rapide sur Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3
Et une solution générique qui prend une fonction de mappeur (un peu plus lente que la carte directe, mais c'est prévu):
la source
J'ai commencé à coller Underscore dans tous les nouveaux projets par défaut, donc je n'ai jamais à penser à ces petits problèmes de transfert de données.
Produit
[17, 35]
.la source
Voici une autre façon de résoudre ce problème:
Je ne sais pas à quelle vitesse cette solution est comparée aux autres, mais j'aime le look plus propre. ;-)
EDIT: D'accord, ce qui précède semble être la solution la plus lente de toutes ici.
J'ai créé un cas de test de performance ici: http://jsperf.com/distinct-values-from-array
Au lieu de tester pour les âges (Integers), j'ai choisi de comparer les noms (Strings).
La méthode 1 (solution de TS) est très rapide. Chose intéressante, la méthode 7 surpasse toutes les autres solutions, ici je viens de me débarrasser de .indexOf () et j'en ai utilisé une implémentation "manuelle", en évitant les appels en boucle:
La différence de performances avec Safari et Firefox est incroyable, et il semble que Chrome fasse le meilleur travail d'optimisation.
Je ne sais pas exactement pourquoi les extraits ci-dessus sont si rapides par rapport aux autres, peut-être que quelqu'un de plus sage que moi a une réponse. ;-)
la source
utilisant lodash
la source
Utiliser Lodash
Renvoie [17,35]
la source
la source
underscore.js
_.uniq(_.pluck(array,"age"))
la source
Voici une solution polyvalente qui utilise réduire, permet le mappage et maintient l'ordre d'insertion.
éléments : un tableau
mapper : fonction unaire qui mappe l'élément aux critères, ou vide pour mapper l'élément lui-même.
Usage
Vous pouvez l'ajouter à votre prototype Array et laisser de côté le paramètre items si c'est votre style ...
Vous pouvez également utiliser un ensemble au lieu d'un tableau pour accélérer la correspondance.
la source
la source
Je viens de le trouver et je l'ai trouvé utile
Encore une fois en utilisant le soulignement , donc si vous avez un objet comme celui-ci
il vous donnera uniquement les objets uniques.
Ce qui se passe ici, c'est que
indexBy
renvoie une carte comme celle-ciet juste parce que c'est une carte, toutes les clés sont uniques.
Ensuite, je mappe simplement cette liste sur le tableau.
Si vous n'avez besoin que des valeurs distinctes
Gardez à l'esprit que le
key
est retourné sous forme de chaîne, donc si vous avez besoin d'entiers à la place, vous devriez fairela source
je pense que vous recherchez la fonction groupBy (en utilisant Lodash)
produit un résultat:
Démo jsFiddle: http://jsfiddle.net/4J2SX/201/
la source
Si, comme moi, vous préférez une version plus "fonctionnelle" sans compromettre la vitesse, cet exemple utilise une recherche rapide de dictionnaire enveloppée à l'intérieur pour réduire la fermeture.
Selon ce test, ma solution est deux fois plus rapide que la réponse proposée
la source
la source
Je sais que mon code est peu long et peu complexe, mais il est compréhensible, j'ai donc essayé de cette façon.
J'essaie de développer ici une fonction basée sur un prototype et le code change également.
Ici, Distinct est ma propre fonction prototype.
la source
Si vous avez Array.prototype.includes ou êtes prêt à le polyfill , cela fonctionne:
la source
Mon code ci-dessous affichera le tableau unique des âges ainsi que le nouveau tableau n'ayant pas d'âge en double
la source
J'ai écrit le mien en TypeScript, pour un cas générique, comme celui de Kotlin
Array.distinctBy {}
...Où
U
est lavable, bien sûr. Pour les objets, vous pourriez avoir besoin de https://www.npmjs.com/package/es6-json-stable-stringifyla source
Si vous avez besoin d'un objet unique
[Objet {x: 1, y: 2}, Objet {x: 2, y: 1}]
la source
Répondre à cette vieille question est assez inutile, mais il existe une réponse simple qui parle de la nature de Javascript. Les objets en Javascript sont intrinsèquement des tables de hachage. Nous pouvons l'utiliser pour obtenir un hachage de clés uniques:
Ensuite, nous pouvons réduire le hachage à un tableau de valeurs uniques:
C'est tout ce dont vous avez besoin. Le tableau a2 contient uniquement les âges uniques.
la source
Une doublure simple avec de grandes performances. 6% plus rapide que les solutions ES6 dans mes tests .
la source
array.map( o => o.age).filter( (v,i,a) => a.indexOf(v)===i)
. J'utiliser le mot - clé de fonction si rarement maintenant que je dois lire des choses deux fois quand je le vois 😊