J'ai un tableau de nombres dont je dois m'assurer qu'ils sont uniques. J'ai trouvé l'extrait de code ci-dessous sur Internet et cela fonctionne très bien jusqu'à ce que le tableau contienne un zéro. J'ai trouvé cet autre script ici sur Stack Overflow qui lui ressemble presque exactement, mais il n'échoue pas.
Donc, pour m'aider à apprendre, quelqu'un peut-il m'aider à déterminer où le script prototype va mal?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
Plus de réponses à la question en double:
Question similaire:
javascript
arrays
unique
Mottie
la source
la source
o
=object
,a
=array
,i
=index
ete
= umm, quelque chose: PRéponses:
Avec JavaScript 1.6 / ECMAScript 5, vous pouvez utiliser la
filter
méthode native d'un tableau de la manière suivante pour obtenir un tableau avec des valeurs uniques:La méthode native
filter
parcourra le tableau et ne laissera que les entrées qui passent la fonction de rappel donnéeonlyUnique
.onlyUnique
vérifie si la valeur donnée est la première survenue. Sinon, il doit s'agir d'un doublon et ne sera pas copié.Cette solution fonctionne sans bibliothèque supplémentaire comme jQuery ou prototype.js.
Cela fonctionne également pour les tableaux avec des types de valeurs mixtes.
Pour les anciens navigateurs (<ie9), qui ne prennent pas en charge les méthodes natives
filter
etindexOf
vous pouvez trouver des solutions dans la documentation MDN pour filter et indexOf .Si vous souhaitez conserver la dernière occurrence d'une valeur, remplacez simplement
indexOf
parlastIndexOf
.Avec ES6, cela pourrait être raccourci:
Merci à Camilo Martin pour un indice en commentaire.
ES6 possède un objet natif
Set
pour stocker des valeurs uniques. Pour obtenir un tableau avec des valeurs uniques, vous pouvez maintenant faire ceci:Le constructeur de
Set
prend un objet itérable, comme Array, et l'opérateur de propagation...
transforme l'ensemble en un tableau. Merci à Lukas Liese pour un indice en commentaire.la source
['a', 1, 'a', 2, '1']
vous obtiendrez['a', 1, 2]
. Mais ce n'est pas ce que j'attendais. BTW, beaucoup plus lent est très relatif..filter((v,i,a)=>a.indexOf(v)==i)
(notation de flèche grasse).let unique_values = [...new Set(random_array)];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Réponse mise à jour pour ES6 / ES2015 : à l'aide de l' ensemble , la solution unifilaire est:
Qui revient
Comme suggéré par le_m , cela peut également être raccourci à l'aide de l' opérateur d'étalement , comme
la source
Array.from(new Set([[1,2],[1,2],[1,2,3]]))
myArray.filter((v, i, a) => a.indexOf(v) === i);
?Set
et ajoutez des objets au lieu de valeurs primitives, il contiendra des références uniques aux objets. Ainsi, l'ensembles
danslet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);
renverra ceci:Set { { Foo: 'Bar' }, { Foo: 'Bar' } }
qui est unSet
avec des références d'objet uniques aux objets qui contiennent les mêmes valeurs. Si vous écrivezlet o = {Foo:"Bar"};
puis créez un ensemble avec deux références comme cecilet s2 = new Set([o,o]);
Set { { Foo: 'Bar' } }
new Set
au trophée deJe me rends compte que cette question a déjà plus de 30 réponses. Mais j'ai d'abord lu toutes les réponses existantes et fait mes propres recherches.
J'ai divisé toutes les réponses en 4 solutions possibles:
[...new Set( [1, 1, 2] )];
{ }
pour éviter les doublons[ ]
filter + indexOf
Voici des exemples de codes trouvés dans les réponses:
Utilisez la nouvelle fonctionnalité ES6:
[...new Set( [1, 1, 2] )];
Utiliser un objet
{ }
pour éviter les doublonsUtiliser un tableau d'assistance
[ ]
Utilisation
filter + indexOf
Et je me suis demandé laquelle est la plus rapide. J'ai créé un exemple de feuille Google pour tester les fonctions. Remarque: ECMA 6 n'est pas disponible dans Google Sheets, je ne peux donc pas le tester.
Voici le résultat des tests:
Je m'attendais à voir que le code utilisant l'objet
{ }
gagnera parce qu'il utilise du hachage. Je suis donc heureux que les tests aient montré les meilleurs résultats pour cet algorithme dans Chrome et IE. Merci à @rab pour le code .la source
Vous pouvez également utiliser underscore.js .
qui retournera:
la source
array = [...new Set(array)]
One Liner, Pure JavaScript
Avec la syntaxe ES6
list = list.filter((x, i, a) => a.indexOf(x) == i)
Avec la syntaxe ES5
Compatibilité du navigateur : IE9 +
la source
J'ai depuis trouvé une belle méthode qui utilise jQuery
Remarque: Ce code a été tiré du poste de frappe de canard de Paul Irish - j'ai oublié de donner le crédit: P
la source
Solution la plus courte avec ES6:
[...new Set( [1, 1, 2] )];
Ou si vous souhaitez modifier le prototype Array (comme dans la question d'origine):
EcmaScript 6 n'est implémenté que partiellement dans les navigateurs modernes pour le moment (août 2015), mais Babel est devenu très populaire pour repasser ES6 (et même ES7) vers ES5. De cette façon, vous pouvez écrire du code ES6 aujourd'hui!
Si vous vous demandez ce que cela
...
signifie, cela s'appelle l' opérateur de propagation . D'après MDN : «L'opérateur d'étalement permet de développer une expression dans des endroits où plusieurs arguments (pour les appels de fonction) ou plusieurs éléments (pour les littéraux de tableau) sont attendus». Parce qu'un ensemble est un itérable (et ne peut avoir que des valeurs uniques), l'opérateur de propagation étendra l'ensemble pour remplir le tableau.Ressources pour apprendre ES6:
la source
a = [...Set(a)]
, mais, de toute façon, ce n'est que Firefox, pour l'instant.require ( "core-js/fn/array/from" );
[...Set(['a', 1, 'a', 2, '1'])]
va lancer une TypeError, il est donc toujours sage de conservernew
:[...new Set(['a', 1, 'a', 2, '1'])]
Solution la plus simple:
Ou:
la source
La façon la plus simple et la plus rapide (dans Chrome) de procéder:
Parcoure simplement chaque élément du tableau, teste si cet élément est déjà dans la liste, et si ce n'est pas le cas, poussez vers le tableau qui est retourné.
Selon jsPerf, cette fonction est la plus rapide de celles que j'ai pu trouver n'importe où - n'hésitez pas à ajouter la vôtre.
La version non prototype:
Tri
Lorsque vous devez également trier le tableau, ce qui suit est le plus rapide:
ou non prototype:
C'est également plus rapide que la méthode ci-dessus dans la plupart des navigateurs non-chrome.
la source
unique
fonction a une complexité O (n ^ 2) tandis que celui dansgetUnique
est O (n). Le premier peut être plus rapide sur de petits ensembles de données, mais comment pouvez-vous discuter avec les mathématiques :) Vous pouvez vous assurer que le dernier est plus rapide si vous l'exécutez sur un tableau, disons, d'1e5 éléments uniquesPERFORMANCE UNIQUEMENT! ce code est probablement 10 fois plus rapide que tous les codes ici * fonctionne sur tous les navigateurs et a également l'impact mémoire le plus faible .... et plus
si vous n'avez pas besoin de réutiliser l'ancien tableau; btw effectuer les autres opérations nécessaires avant de le convertir en unique ici est probablement le moyen le plus rapide de le faire, également très court.
alors vous pouvez essayer ceci
Je suis venu avec cette fonction en lisant cet article ...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
Je n'aime pas la boucle for. il a de nombreux paramètres.j'aime la boucle while--. while est la boucle la plus rapide de tous les navigateurs, à l'exception de celle que nous aimons tous tellement ... chrome.
de toute façon j'ai écrit la première fonction qui utilise while.Et oui c'est un peu plus rapide que la fonction trouvée dans l'article.mais pas assez.
unique2()
prochaine étape, utilisez js moderne.
Object.keys
j'ai remplacé l'autre pour la boucle par les Object.keys de js1.7 ... un peu plus rapide et plus court (en chrome 2x plus rapide);). Pas assez!.unique3()
.à ce stade, je pensais à ce dont j'avais vraiment besoin dans MA fonction unique. je n'ai pas besoin de l'ancien tableau, je veux une fonction rapide. j'ai donc utilisé 2 while boucles + épissure.
unique4()
Inutile de dire que j'ai été impressionné.
chrome: les 150 000 opérations par seconde habituelles sont passées à 1 800 000 opérations par seconde.
soit: 80 000 op / s vs 3 500 000 op / s
ios: 18 000 op / s contre 170 000 op / s
safari: 80 000 op / s vs 6 000 000 op / s
Preuve http://jsperf.com/wgu ou mieux utiliser console.time ... microtime ... peu importe
unique5()
est juste pour vous montrer ce qui se passe si vous souhaitez conserver l'ancien tableau.Ne l'utilisez pas
Array.prototype
si vous ne savez pas ce que vous faites. je viens de faire beaucoup de copie et de passé. À utiliserObject.defineProperty(Array.prototype,...,writable:false,enumerable:false})
si vous souhaitez créer un prototype natif.exemple : https://stackoverflow.com/a/20463021/2450730Démo http://jsfiddle.net/46S7g/
REMARQUE: votre ancienne baie est détruite / devient unique après cette opération.
si vous ne pouvez pas lire le code ci-dessus demandez, lisez un livre javascript ou voici quelques explications sur le code plus court. https://stackoverflow.com/a/21353032/2450730
certains utilisent
indexOf
... ne pas ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfhpour les tableaux vides
la source
Beaucoup de réponses ici peuvent ne pas être utiles aux débutants. Si la déduplication d'un tableau est difficile, connaîtront-ils vraiment la chaîne du prototype, ou même jQuery?
Dans les navigateurs modernes, une solution propre et simple consiste à stocker des données dans un ensemble , conçu pour être une liste de valeurs uniques.
Le
Array.from
est utile pour reconvertir l'ensemble en tableau afin que vous ayez un accès facile à toutes les méthodes (fonctionnalités) impressionnantes dont disposent les tableaux. Il existe également d' autres façons de faire la même chose. Mais vous n'aurez peut-être pas besoinArray.from
du tout, car les ensembles ont de nombreuses fonctionnalités utiles comme forEach .Si vous devez prendre en charge l'ancien Internet Explorer et ne pouvez donc pas utiliser Set, une technique simple consiste à copier des éléments dans un nouveau tableau tout en vérifiant au préalable s'ils sont déjà dans le nouveau tableau.
Pour le rendre instantanément réutilisable, mettons-le dans une fonction.
Donc, pour nous débarrasser des doublons, nous le ferions maintenant.
La
deduplicate(cars)
partie devient la chose que nous avons appelé résultat lorsque la fonction de finalise de.Passez-lui simplement le nom du tableau que vous aimez.
la source
la source
push
l'élément au tableau au lieu de l'utiliserconcat
? J'ai essayé d'utiliser push et cela a échoué. Je cherche une explication.[0,1,2,0,3,2,1,5].reduce((prev, cur) => ~prev.indexOf(cur) ? prev : prev.concat([cur]), []);
NaN
convivialeNous pouvons le faire en utilisant des ensembles ES6:
// La sortie sera
la source
Ce prototype
getUnique
n'est pas totalement correct, car si j'ai un tableau comme:["1",1,2,3,4,1,"foo"]
il retournera["1","2","3","4"]
et"1"
est une chaîne et1
est un entier; ils sont différents.Voici une bonne solution:
en utilisant:
Ce qui précède produira
["1",2,3,4,1,"foo"]
.la source
$foo = 'bar'
c'est la façon PHP de déclarer des variables. Cela fonctionnera en javascript, mais créera un global implicite, et ne devrait généralement pas être fait.$foo
c'est la façon de déclarer des variables en javascript alors qu'elle l'var foo
est réellement .Sans étendre Array.prototype (on dit que c'est une mauvaise pratique) ou utiliser jquery / underscore, vous pouvez simplement
filter
le tableau.En gardant la dernière occurrence:
ou première occurrence:
Eh bien, c'est seulement javascript ECMAScript 5+, ce qui signifie seulement IE9 +, mais c'est bien pour un développement en HTML / JS natif (Windows Store App, Firefox OS, Sencha, Phonegap, Titanium, ...).
la source
filter
. Sur la page MDN, ils ont une implémentation pour Internet Explorer, je veux dire, des navigateurs plus anciens. Aussi: JS 1.6 se réfère uniquement au moteur js de Firefox, mais la bonne chose à dire c'est qu'il s'agit d'ECMAScript 5.la magie
O (n) performance ; nous supposons que votre tableau est dans
a
ett={}
. Explication ici (+ Impr . Jeppe )Afficher l'extrait de code
la source
in
opérateur en dehors de l'autre construction que lafor
boucle: P) - Merci - je l'apprécie et je donnerai +2 à vos autres bonnes réponses .t
qui reste vivante après le filtrage… ??la source
Si vous utilisez le framework Prototype, il n'est pas nécessaire de faire des boucles 'for', vous pouvez utiliser http://www.prototypejs.org/api/array/uniq comme ceci:
Ce qui produira un tableau en double sans doublons. Je suis tombé sur votre question en cherchant une méthode pour compter les enregistrements de tableaux distincts donc après
j'ai utilisé
et il y avait mon résultat simple. ps Désolé si j'ai mal écrit quelque chose
modifier: si vous voulez échapper aux enregistrements non définis, vous pouvez ajouter
avant, comme ça:
la source
Maintenant, en utilisant des ensembles, vous pouvez supprimer les doublons et les reconvertir en tableau.
Une autre solution consiste à utiliser le tri et le filtrage
la source
C'est parce que
0
c'est une valeur fausse en JavaScript.this[i]
sera falsifié si la valeur du tableau est 0 ou toute autre valeur falsifiée.la source
la source
o
au lieu d'un simple1
, bien que la comparaison d'égalité soit toujours dans le sens des chaînes (bien que, parmi toutes les égalités Javascript possibles, cela ne semble pas trop déraisonnable).J'ai eu un problème légèrement différent où j'avais besoin de supprimer des objets avec des propriétés d'ID en double d'un tableau. cela a fonctionné.
la source
La réponse la plus simple est:
la source
Je ne sais pas pourquoi Gabriel Silveira a écrit la fonction de cette façon, mais une forme plus simple qui fonctionne aussi bien pour moi et sans la minification est:
ou en CoffeeScript:
la source
Si vous êtes d'accord avec des dépendances supplémentaires, ou si vous avez déjà l'une des bibliothèques dans votre base de code, vous pouvez supprimer les doublons d'un tableau en place à l'aide de LoDash (ou Underscore).
Usage
Si vous ne l'avez pas déjà dans votre base de code, installez-le à l'aide de npm:
Ensuite, utilisez-le comme suit:
En dehors:
la source
On y a beaucoup répondu, mais cela n'a pas répondu à mon besoin particulier.
De nombreuses réponses sont comme ceci:
Mais cela ne fonctionne pas pour les tableaux d'objets complexes.
Disons que nous avons un tableau comme celui-ci:
Si nous voulons que les objets avec des noms uniques, nous devons utiliser à la
array.prototype.findIndex
place dearray.prototype.indexOf
:la source
De Shamasis Bhattacharya blog de (O (2n) la complexité du temps):
Du blog de Paul Irish : amélioration sur JQuery
.unique()
:la source
Trouver des valeurs de tableau uniques dans une méthode simple
la source
Il semble que nous ayons perdu la réponse de Rafael , qui a été la réponse acceptée pendant quelques années. C'était (au moins en 2017) la solution la plus performante si vous n'avez pas de tableau de type mixte :
Si vous n'avez un tableau de type mixte, vous pouvez sérialiser la clé de hachage:
la source
Pour résoudre le problème dans l'autre sens, il peut être utile de ne pas avoir de doublon pendant le chargement de votre tableau, comme le ferait l'objet Set, mais il n'est pas encore disponible dans tous les navigateurs. Il économise de la mémoire et est plus efficace si vous avez besoin de regarder son contenu plusieurs fois.
Échantillon:
Vous donne
set = [1,3,4,2]
la source