Je voudrais comparer deux tableaux ... idéalement, efficacement. Rien d'extraordinaire, juste true
s'ils sont identiques, etfalse
sinon. Sans surprise, l'opérateur de comparaison ne semble pas fonctionner.
var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2); // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2)); // Returns true
Le codage JSON de chaque tableau le fait, mais existe-t-il un moyen plus rapide ou "meilleur" de comparer simplement les tableaux sans avoir à parcourir chaque valeur?
javascript
arrays
json
Julian H. Lam
la source
la source
([] == []) == false
.Réponses:
Pour comparer des tableaux, parcourez-les et comparez chaque valeur:
Comparaison des tableaux:
Usage:
Vous pouvez dire " Mais il est beaucoup plus rapide de comparer des chaînes - pas de boucles ... " eh bien, alors vous devriez noter qu'il existe des boucles. Première boucle récursive qui convertit Array en chaîne et seconde, qui compare deux chaînes. Cette méthode est donc plus rapide que l'utilisation de chaîne .
Je crois que de plus grandes quantités de données devraient toujours être stockées dans des tableaux, pas dans des objets. Cependant, si vous utilisez des objets, ils peuvent également être partiellement comparés.
Voici comment:
Comparaison d'objets:
J'ai indiqué ci-dessus, que deux instances d' objet ne seront jamais égales, même si elles contiennent les mêmes données pour le moment:
Cela a une raison, car il peut y avoir, par exemple, des variables privées dans les objets.
Cependant, si vous utilisez simplement la structure d'objet pour contenir des données, la comparaison est toujours possible:
Cependant, n'oubliez pas que celui-ci doit servir à comparer des données similaires à JSON, pas des instances de classe et d'autres choses. Si vous voulez comparer des objets plus complexes, regardez cette réponse et sa fonction super longue .
Pour que cela fonctionne avec,
Array.equals
vous devez éditer un peu la fonction d'origine:J'ai fait un petit outil de test pour les deux fonctions .
Bonus: tableaux imbriqués avec
indexOf
etcontains
Samy Bencherif a préparé des fonctions utiles pour le cas où vous recherchez un objet spécifique dans des tableaux imbriqués, qui sont disponibles ici: https://jsfiddle.net/SamyBencherif/8352y6yw/
la source
this[i] !== array[i]
plutôt que!=
.equals
place decompare
. Au moins dans .NET, compare renvoie généralement un entier signé indiquant quel objet est plus grand que l'autre. Voir: Comparer.Comparer .Bien que cela ne fonctionne que pour les tableaux scalaires (voir la note ci-dessous), il est court:
Rr, dans ECMAScript 6 / CoffeeScript / TypeScript avec fonctions fléchées:
(Remarque: «scalaire» signifie ici des valeurs qui peuvent être comparées directement en utilisant
===
. Donc: nombres, chaînes, objets par référence, fonctions par référence. Voir la référence MDN pour plus d'informations sur les opérateurs de comparaison).MISE À JOUR
D'après ce que j'ai lu dans les commentaires, le tri du tableau et la comparaison peuvent donner un résultat précis:
Par exemple:
Ensuite, le code ci-dessus donnerait
true
la source
a1.length==a2.length && a1.every((v,i)=>a2.includes(v))
:var a1 =[1,2,3], a2 = [3,2,1];
(var a1 =[1,3,3], a2 = [1,1,3];
ne fonctionnera pas comme prévu)J'aime utiliser la bibliothèque Underscore pour les projets de codage lourds de tableaux / objets ... dans Underscore et Lodash, que vous compariez des tableaux ou des objets, cela ressemble à ceci:
la source
_.isEqual([1,2,3], [2,1,3]) => false
isEqual
fonctionnalité, vous pouvez toujours utiliser le module_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Je pense que c'est la façon la plus simple de le faire en utilisant JSON stringify, et cela peut être la meilleure solution dans certaines situations:
Cela convertit les objets
a1
eta2
en chaînes afin qu'ils puissent être comparés. L'ordre est important dans la plupart des cas, car cela peut trier l'objet à l'aide d'un algorithme de tri indiqué dans l'une des réponses ci-dessus.Veuillez noter que vous ne comparez plus l'objet mais la représentation sous forme de chaîne de l'objet. Ce n'est peut-être pas exactement ce que vous voulez.
la source
On ne sait pas ce que vous entendez par «identique». Par exemple, les tableaux
a
etb
ci - dessous sont-ils identiques (notez les tableaux imbriqués)?Voici une fonction de comparaison de tableau optimisée qui compare tour à tour les éléments correspondants de chaque tableau en utilisant une stricte égalité et ne fait pas de comparaison récursive des éléments de tableau qui sont eux-mêmes des tableaux, ce qui signifie que pour l'exemple ci-dessus,
arraysIdentical(a, b)
cela reviendraitfalse
. Cela fonctionne dans le cas général, que lesjoin()
solutions basées sur JSON et ne permettront pas:la source
true
. La réponse explique que non. Si vous devez comparer des tableaux imbriqués, vous pouvez facilement ajouter une vérification récursive.La voie pratique
Je pense qu'il est faux de dire qu'une implémentation particulière est "The Right Way ™" si elle n'est que "correcte" ("correcte") contrairement à une "mauvaise" solution. La solution de Tomáš est une nette amélioration par rapport à la comparaison de tableaux basés sur des chaînes, mais cela ne signifie pas qu'elle est objectivement "correcte". Qu'est-ce qui est juste toute façon? Est-ce le plus rapide? Est-ce le plus flexible? Est-ce le plus simple à comprendre? Est-ce le débogage le plus rapide? Utilise-t-il le moins d'opérations? Est-ce que cela a des effets secondaires? Aucune solution ne peut avoir le meilleur de toutes choses.
Tomáš pourrait dire que sa solution est rapide mais je dirais aussi que c'est inutilement compliqué. Il essaie d'être une solution tout-en-un qui fonctionne pour toutes les baies, imbriquées ou non. En fait, il accepte même plus que de simples tableaux en entrée et tente toujours de donner une réponse "valide".
Les génériques offrent une réutilisabilité
Ma réponse abordera le problème différemment. Je vais commencer par une
arrayCompare
procédure générique qui ne concerne que la navigation dans les tableaux. À partir de là, nous allons construire nos autres fonctions de comparaison de base commearrayEqual
etarrayDeepEqual
, etc.À mon avis, le meilleur type de code n'a même pas besoin de commentaires, et cela ne fait pas exception. Il se passe tellement peu de choses ici que vous pouvez comprendre le comportement de cette procédure sans presque aucun effort. Bien sûr, une partie de la syntaxe ES6 peut vous sembler étrangère maintenant, mais c'est uniquement parce que ES6 est relativement nouveau.
Comme le type le suggère,
arrayCompare
prend la fonction de comparaisonf
, et deux tableaux d'entrée,xs
etys
. Pour la plupart, tout ce que nous faisons est d'appelerf (x) (y)
pour chaque élément dans les tableaux d'entrée. Nous retournons tôtfalse
si la valeur définie par l'utilisateurf
revientfalse
- grâce à&&
l'évaluation des courts-circuits de. Donc oui, cela signifie que le comparateur peut arrêter l'itération plus tôt et empêcher le bouclage à travers le reste du tableau d'entrée lorsqu'il n'est pas nécessaire.Comparaison stricte
Ensuite, en utilisant notre
arrayCompare
fonction, nous pouvons facilement créer d'autres fonctions dont nous pourrions avoir besoin. Commençons par l'élémentairearrayEqual
…Aussi simple que cela.
arrayEqual
peut être défini avecarrayCompare
et une fonction de comparaison qui se comparea
à l'b
utilisation===
(pour une stricte égalité).Notez que nous définissons également
equal
comme sa propre fonction. Cela met en évidence le rôle d'arrayCompare
une fonction d'ordre supérieur pour utiliser notre comparateur de premier ordre dans le contexte d'un autre type de données (Array).Comparaison lâche
Nous pourrions tout aussi facilement définir en
arrayLooseEqual
utilisant un à la==
place. Maintenant, en comparant1
(Number) à'1'
(String), le résultat seratrue
…Comparaison approfondie (récursive)
Vous avez probablement remarqué que ce n'est qu'une comparaison superficielle. La solution de Tomáš est sûrement "The Right Way ™" car elle implique une comparaison profonde implicite, n'est-ce pas?
Eh bien, notre
arrayCompare
procédure est suffisamment polyvalente pour être utilisée de manière à ce qu'un test d'égalité approfondi soit un jeu d'enfant…Aussi simple que cela. Nous construisons un comparateur profond en utilisant une autre fonction d'ordre supérieur. Cette fois, nous
arrayCompare
utilisons un comparateur personnalisé qui vérifiera sia
etb
sont des tableaux. Si tel est le cas, réappliquezarrayDeepCompare
sinon comparera
etb
au comparateur spécifié par l'utilisateur (f
). Cela nous permet de séparer le comportement de comparaison approfondie de la façon dont nous comparons réellement les éléments individuels. C'est-à-dire, comme le montre l'exemple ci-dessus, nous pouvons comparer en profondeur en utilisantequal
,looseEqual
ou tout autre comparateur que nous faisons.Parce qu'il
arrayDeepCompare
est curry, nous pouvons l'appliquer partiellement comme nous l'avons fait dans les exemples précédentsPour moi, c'est déjà une nette amélioration par rapport à la solution de Tomáš car je peux explicitement choisir une comparaison superficielle ou profonde pour mes tableaux, selon les besoins.
Comparaison d'objets (exemple)
Et si vous avez un tableau d'objets ou quelque chose? Peut-être que vous voulez considérer ces tableaux comme «égaux» si chaque objet a la même
id
valeur…Aussi simple que cela. Ici, j'ai utilisé des objets JS vanilla, mais ce type de comparateur pourrait fonctionner pour n'importe quel type d'objet; même vos objets personnalisés. La solution de Tomáš devrait être complètement retravaillée pour prendre en charge ce type de test d'égalité
Tableau profond avec des objets? Pas de problème. Nous avons créé des fonctions génériques très polyvalentes, afin qu'elles fonctionnent dans une grande variété de cas d'utilisation.
Comparaison arbitraire (exemple)
Ou si vous vouliez faire une autre sorte de comparaison complètement arbitraire? Peut-être que je veux savoir si chacun
x
est plus grand que chacuny
…Moins est plus
Vous pouvez voir que nous faisons plus avec moins de code. Il n'y a rien de compliqué en
arrayCompare
soi et chacun des comparateurs personnalisés que nous avons créés a une implémentation très simple.Avec facilité, nous pouvons définir exactement comment nous voulons deux tableaux à comparer - peu profond, profond, stricte, lâche, une propriété d'objet, ou un calcul arbitraire, ou toute combinaison de ceux - ci - tout en utilisant une procédure ,
arrayCompare
. Peut-être même imaginer unRegExp
comparateur! Je sais à quel point les enfants adorent ces expressions régulières…Est-ce le plus rapide? Nan. Mais ce n'est probablement pas nécessaire non plus. Si la vitesse est la seule métrique utilisée pour mesurer la qualité de notre code, beaucoup de très bon code serait jeté - C'est pourquoi j'appelle cette approche The Practical Way . Ou peut-être pour être plus juste, A pratique. Cette description convient à cette réponse parce que je ne dis pas que cette réponse n'est pratique que par rapport à une autre réponse; c'est objectivement vrai. Nous avons atteint un degré élevé de fonctionnalité avec très peu de code très facile à raisonner. Aucun autre code ne peut dire que nous n'avons pas mérité cette description.
Est-ce que cela en fait la «bonne» solution pour vous? C'est à vous de décider. Et personne d'autre ne peut le faire pour vous; vous seul savez quels sont vos besoins. Dans presque tous les cas, j'apprécie le code simple, pratique et polyvalent plutôt que le type intelligent et rapide. Ce que vous appréciez peut différer, alors choisissez ce qui vous convient.
Éditer
Mon ancienne réponse était plus axée sur la décomposition
arrayEqual
en minuscules procédures. C'est un exercice intéressant, mais ce n'est pas vraiment la meilleure façon (la plus pratique) d'aborder ce problème. Si vous êtes intéressé, vous pouvez voir cet historique de révision.la source
arrayCompare
? Oui, la fonction est curry, mais elle diffère desome
etevery
.arrayCompare
prend un comparateur et deux tableaux pour comparer. J'ai choisi un nom spécifiquement générique car nous pouvons comparer des tableaux en utilisant n'importe quelle fonction arbitraire. La fonction est curry afin qu'elle puisse être spécialisée pour créer de nouvelles fonctions de comparaison de tableaux (par exemple,arrayEqual
). Pouvez-vous suggérer un meilleur nom? Dans quels domaines pensez-vous avoir besoin de commentaires ou d'explications supplémentaires? Je suis heureux de discuter ^ _ ^Dans l'esprit de la question d'origine:
J'ai effectué des tests de performances sur certaines des suggestions les plus simples proposées ici avec les résultats suivants (rapide à lent):
tandis que (67%) par Tim Down
chaque (69%) par utilisateur2782196
réduire (74%) par les DEI
join & toString (78%) par Gaizka Allende & vivek
demi toString (90%) par Victor Palomo
stringify (100%) par radtek
la source
Array.from({length: 1000}).map((a,v)=>
$ {v}.padStart(10,2));
En s'appuyant sur la réponse de Tomáš Zato, je conviens que le simple fait de parcourir les tableaux est le plus rapide. De plus (comme d'autres l'ont déjà dit), la fonction doit être appelée égal / égal, pas comparer. À la lumière de cela, j'ai modifié la fonction pour gérer la comparaison des tableaux pour la similitude - c'est-à-dire qu'ils ont les mêmes éléments, mais hors service - pour un usage personnel, et j'ai pensé que je la mettrais ici pour que tout le monde puisse la voir.
Cette fonction prend un paramètre supplémentaire strict qui vaut par défaut true. Ce paramètre strict définit si les tableaux doivent être totalement égaux dans le contenu et l'ordre de ces contenus, ou simplement contenir le même contenu.
Exemple:
J'ai également rédigé un rapide jsfiddle avec la fonction et cet exemple:
http://jsfiddle.net/Roundaround/DLkxX/
la source
Même si cela a beaucoup de réponses, une que je pense être utile:
Il n'est pas indiqué dans la question à quoi ressemblera la structure du tableau, donc si vous savez avec certitude que vous n'aurez pas de tableaux ni d'objets imbriqués dans votre tableau (cela m'est arrivé, c'est pourquoi je suis arrivé à ce réponse) le code ci-dessus fonctionnera.
Ce qui se passe, c'est que nous utilisons l'opérateur d'étalement (...) pour concaténer les deux tableaux, puis nous utilisons Set pour éliminer les doublons. Une fois que vous avez cela, vous pouvez comparer leurs tailles, si les trois tableaux ont la même taille, vous êtes prêt à partir.
Cette réponse ignore également l'ordre des éléments , comme je l'ai dit, la situation exacte m'est arrivée, donc peut-être que quelqu'un dans la même situation pourrait se retrouver ici (comme moi).
Modifier 1.
Répondre à la question de Dmitry Grinko: "Pourquoi avez-vous utilisé l'opérateur de propagation (...) ici - ... nouveau Set? Cela ne fonctionne pas"
Considérez ce code:
Tu auras
Pour travailler avec cette valeur, vous devez utiliser certaines propriétés Set (voir https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set ). En revanche, lorsque vous utilisez ce code:
Tu auras
C'est la différence, le premier me donnerait un ensemble, cela fonctionnerait aussi car je pourrais obtenir la taille de cet ensemble, mais le second me donne le tableau dont j'ai besoin, ce qui est plus direct avec la résolution.
la source
Sur les mêmes lignes que JSON.encode est d'utiliser join ().
Le seul problème est que si vous vous souciez des types testés par la dernière comparaison. Si vous vous souciez des types, vous devrez boucler.
Si l'ordre doit rester le même, c'est juste une boucle, aucun tri n'est nécessaire.
la source
.join()
. Peut-être que si vous déclariez votre deuxième solution comme principale (car c'est la meilleure, bien qu'inutile contre les tableaux multidimensionnels), je ne vous jugerais pas de cette façon. Jusqu'à présent, j'ai rétrogradé toutes les réponses qui convertissent les tableaux en chaînes. De plus, j'ai voté pour tous ceux qui utilisent la bonne façon, au cas où vous en auriez besoin. Cela signifie la réponse de @Tim Down et celle de Bireys.checkArrays([1,2,3] , ["1,2",3]) == true
et il est très peu probable que ce soit ce que vous voulez faire!join()
comme ça le rend subtilement buggé!Voici une version Typescript:
Quelques cas de test pour le moka:
la source
Si vous utilisez un framework de test comme Mocha avec la bibliothèque d'assertions Chai , vous pouvez utiliser l' égalité profonde pour comparer les tableaux.
Cela ne devrait retourner vrai que si les tableaux ont des éléments égaux aux indices correspondants.
la source
S'il ne s'agit que de deux tableaux de nombres ou de chaînes, il s'agit d'une ligne rapide
la source
[11]
. Assez évident pour expliquer pourquoi cela se produit et comment y remédier.Dans mon cas, les tableaux comparés ne contiennent que des nombres et des chaînes. Cette fonction vous montrera si les tableaux contiennent les mêmes éléments.
Testons-le!
la source
are_arrs_equal([1,2], [2,1])
. Consultez également d'autres discussions sur cette page pour savoir pourquoi la stringence est inutile, fragile et erronée.are_arrs_equal([1,2], [2,1])
renvoietrue
comme prévu. Cette solution n'est peut-être pas idéale, mais elle a fonctionné pour moi.are_arrs_match([1,2], ["1,2"])
(retournetrue
). Et notez que l'the sort()
appel modifiera les tableaux d'entrée - cela pourrait ne pas être souhaitable.Cela compare 2 tableaux non triés:
la source
Pour un tableau de nombres, essayez:
Afficher l'extrait de code
Remarque: cette méthode ne fonctionnera pas lorsque le tableau contient également des chaînes, par exemple
a2 = [1, "2,3"]
.la source
Nous pourrions le faire de manière fonctionnelle, en utilisant
every
( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every )la source
Votre code ne traitera pas le cas de manière appropriée lorsque les deux tableaux ont les mêmes éléments mais pas dans le même ordre.
Jetez un oeil à mon code avec votre exemple qui compare deux tableaux dont les éléments sont des nombres, vous pouvez le modifier ou l'étendre pour d'autres types d'éléments (en utilisant .join () au lieu de .toString ()).
la source
Voici ma solution:
Fonctionne avec n'importe quelle structure de données imbriquée et ignore évidemment les méthodes des objets. Ne pensez même pas à étendre Object.prototype avec cette méthode, quand j'ai essayé une fois, jQuery s'est cassé;)
Pour la plupart des baies, c'est toujours plus rapide que la plupart des solutions de sérialisation. C'est probablement la méthode de comparaison la plus rapide pour les tableaux d'enregistrements d'objets.
la source
equal({}, {a:1})
etequal({}, null)
et cela se trompe:equal({a:2}, null)
C'est comme ça que je l'ai fait.
la source
Comparaison de 2 tableaux:
fonction d'appel
la source
Je crois en clair
JS
et avecECMAScript 2015
, ce qui est doux et simple à comprendre.j'espère que cela aidera quelqu'un.
la source
Extension de l'idée de Tomáš Zato. Le tableau Array.prototype.compare de Tomas doit être en fait appelé Array.prototype.compareIdentical.
Il transmet:
Mais échoue:
Voici la meilleure version (à mon avis):
http://jsfiddle.net/igos/bcfCY/
la source
////// OU ///////
la source
Une autre approche avec très peu de code (en utilisant Array Reduce et Array includes ):
Si vous voulez comparer également l'égalité de commande:
La
length
vérification garantit que l'ensemble des éléments d'un tableau n'est pas seulement un sous-ensemble de l'autre.Le réducteur est utilisé pour parcourir un tableau et rechercher chaque élément dans un autre tableau. Si un élément n'est pas trouvé, la fonction de réduction revient
false
.la source
Une approche simple:
la source
Déjà de bonnes réponses, mais je voudrais partager une autre idée qui s'est révélée fiable pour comparer les tableaux. Nous pouvons comparer deux tableaux à l'aide de JSON.stringify () . Il créera une chaîne hors du tableau et comparera ainsi deux chaînes obtenues à partir de deux tableaux pour l'égalité
la source
Récursive et travaux sur IMBRIQUÉS tableaux:
la source
Fonctionne avec de MULTIPLES arguments avec des tableaux NESTED :
la source
la source