Comment comparer des tableaux en JavaScript?

j'aimerais comparer deux tableaux... idéalement, efficacement. Rien de fantaisiste, juste true si elles sont identiques, et false si non. Il n'est pas surprenant, 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

encodage JSON chaque tableau n', mais est-il plus rapide ou de la "meilleure" façon de simplement comparer des tableaux sans avoir à parcourir chaque valeur?

699
demandé sur user633183 2011-10-20 18:27:57

30 réponses

pour comparer les tableaux, les passer en boucle et comparer toutes les valeurs:

la Comparaison des tableaux:

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

Utilisation:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

vous pouvez dire mais il est beaucoup plus rapide de comparer des cordes - pas de boucles... " alors, vous devriez noter qu'il y a des boucles. La première boucle récursive qui convertit le tableau en chaîne et la seconde, qui compare deux chaînes. Donc cette méthode est plus rapide que l'utilisation de la corde .

je crois que de plus grandes quantités de données devraient toujours être stockées dans des tableaux, pas dans des objets. Toutefois, si vous utilisez des objets, ils peuvent être partiellement comparé trop.

Voici comment:

objets de Comparaison:

j'ai dit plus haut, que deux objets instances ne seront jamais égaux, même s'ils contiennent le même données actuelles:

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666})  //false

cela a une raison, puisqu'il peut y avoir, par exemple variables privées dans les objets.

cependant, si vous utilisez seulement la structure d'objet pour contenir des données, la comparaison est encore possible:

Object.prototype.equals = function(object2) {
    //For the first loop, we only check for types
    for (propName in this) {
        //Check for inherited methods and properties - like .equals itself
        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
        //Return false if the return value is different
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        //Check instance type
        else if (typeof this[propName] != typeof object2[propName]) {
            //Different types => not equal
            return false;
        }
    }
    //Now a deeper check using other objects property names
    for(propName in object2) {
        //We must check instances anyway, there may be a property that only exists in object2
            //I wonder, if remembering the checked values from the first loop would be faster or not 
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        else if (typeof this[propName] != typeof object2[propName]) {
            return false;
        }
        //If the property is inherited, do not check any more (it must be equa if both objects inherit it)
        if(!this.hasOwnProperty(propName))
          continue;

        //Now the detail check and recursion

        //This returns the script back to the array comparing
        /**REQUIRES Array.equals**/
        if (this[propName] instanceof Array && object2[propName] instanceof Array) {
                   // recurse into the nested arrays
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
                   // recurse into another objects
                   //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        //Normal value comparison for strings and numbers
        else if(this[propName] != object2[propName]) {
           return false;
        }
    }
    //If everything passed, let's say YES
    return true;
}  

cependant, rappelez-vous que celui-ci est de servir dans la comparaison JSON comme des données, pas des instances de classe et d'autres choses. Si vous voulez comparer des objets plus compliqués, regardez cette réponse et c'est superlong fonction .

Pour que cela fonctionne avec Array.equals vous devez éditer un peu la fonction originale:

...
    // Check if we have nested arrays
    if (this[i] instanceof Array && array[i] instanceof Array) {
        // recurse into the nested arrays
        if (!this[i].equals(array[i]))
            return false;
    }
    /**REQUIRES OBJECT COMPARE**/
    else if (this[i] instanceof Object && array[i] instanceof Object) {
        // recurse into another objects
        //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
        if (!this[i].equals(array[i]))
            return false;
        }
    else if (this[i] != array[i]) {
...

j'ai fait un petit outil de test pour les deux fonctions .

Bonus: tableaux imbriqués avec indexOf et contains 1519110920"

Samy Bencherif a préparé 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 /

738
répondu Tomáš Zato 2018-03-10 04:45:08

bien que cela ne fonctionne que pour les tableaux scalaires (Voir note ci-dessous), il est court:

array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})

Rr, dans ECMAScript 6 / CoffeeScript / Tapuscrit avec une Flèche Fonctions:

array1.length === array2.length && array1.every((value, index) => value === array2[index])

(Note:" scalar "signifie ici des valeurs qui peuvent être comparées directement en utilisant === . Donc: des nombres, des chaînes, des objets par référence, les 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 des commentaires, le tri du tableau et la comparaison peuvent donner un résultat précis:

array1.length === array2.length && array1.sort().every(function(value, index) { return value === array2.sort()[index]});

par exemple:

array1 = [2,3,1,4];
array2 = [1,2,3,4];

alors le code ci-dessus donnerait true

244
répondu user2782196 2018-08-07 10:55:00

j'aime utiliser la bibliothèque Underscore pour les projets de codage lourds tableau/objet ... dans Underscore et Lodash, que vous compariez des tableaux ou des objets, cela ressemble à ceci:

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean
162
répondu Jason Boerner 2017-10-05 18:05:16

je pense que c'est la façon la plus simple de le faire en utilisant JSON stringify, et c'est peut-être la meilleure solution dans certaines situations:

JSON.stringify(a1) === JSON.stringify(a2);

cela convertit les objets a1 et a2 en cordes afin qu'ils puissent être comparés. L'ordre est important dans la plupart des cas, car cela peut trier l'objet en utilisant un algorithme de tri montré dans l'une des réponses ci-dessus.

veuillez noter que vous ne comparez plus l'objet mais la chaîne la représentation de l'objet. Il peut ne pas être exactement ce que vous voulez.

69
répondu radtek 2017-05-11 21:34:34

ce n'est pas clair ce que vous voulez dire par"identique". Par exemple, les tableaux a et b sont-ils identiques (notez les tableaux imbriqués)?

var a = ["foo", ["bar"]], b = ["foo", ["bar"]];

Voici une fonction de comparaison de tableau optimisée qui compare les éléments correspondants de chaque tableau à tour de rôle en utilisant l'égalité stricte et ne fait pas la 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) retournerait false . Il fonctionne dans le cas général, que JSON - et join() -solutions basées ne seront pas:

function arraysIdentical(a, b) {
    var i = a.length;
    if (i != b.length) return false;
    while (i--) {
        if (a[i] !== b[i]) return false;
    }
    return true;
};
60
répondu Tim Down 2014-09-04 13:37:23

La Pratique

je pense qu'il est faux de dire qu'une implémentation particulière est" la bonne façon™ "si elle est seulement" correcte "("correcte") par opposition à une solution" erronée". La solution de Tomáš est une nette amélioration par rapport à la comparaison de réseaux à base de cordes, mais cela ne signifie pas que c'est objectivement "juste". Qu'est-ce que droit de toute façon? Est-il le plus rapide? Est-il le plus flexible? Est-il facile à comprendre? Est-il le moyen le plus rapide pour déboguer? Faut-il utiliser le moins d'opérations? A-t-elle des effets secondaires? Nul ne peut avoir la meilleure de toutes les choses.

Tomáš pourrait dire que sa solution est rapide, mais je dirais aussi qu'elle est inutilement compliquée. Il essaie d'être un tout-en-une solution qui fonctionne pour tous les tableaux, imbriqués ou non. En fait, il accepte même plus que juste des tableaux en entrée et tente toujours de donner un "valide" réponse.


Génériques offrent la réutilisabilité

ma réponse abordera le problème différemment. Je vais commencer par une procédure générique arrayCompare qui ne concerne que le passage à travers les tableaux. De là, nous construirons nos autres fonctions de comparaison de base comme arrayEqual et arrayDeepEqual , etc

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

À mon avis, le meilleur type de code n'a même pas besoin de commentaires, et ce n'est pas une exception. Il se passe si peu de choses ici que vous pouvez comprendre le comportement de cette procédure ne demande pratiquement aucun effort. Bien sûr, une partie de la syntaxe ES6 peut sembler étrangère pour vous maintenant, mais c'est seulement parce que ES6 est relativement nouveau.

comme le suggère le type, arrayCompare prend fonction de comparaison, f , et deux tableaux d'entrée, xs et ys . Pour la plupart, Tout ce que nous faisons est d'appeler f (x) (y) pour chaque élément dans les tableaux d'entrée. Nous retournons un ancien false si l'utilisateur défini f retourne false - grâce à l'évaluation du court-circuit de && . Donc oui, cela signifie que le comparateur peut arrêter l'itération tôt et empêcher la boucle dans le reste du tableau d'entrée quand inutile.


comparaison stricte

ensuite, en utilisant notre fonction arrayCompare , nous pouvons facilement créer d'autres fonctions dont nous pourrions avoir besoin. Nous commencerons avec l'élémentaire arrayEqual ...

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

aussi Simple que ça. arrayEqual peut être défini avec arrayCompare et une fonction de comparaison qui compare a à b en utilisant === (pour l'égalité stricte).

notez que nous définissons aussi equal comme sa propre fonction. Cela souligne le rôle de arrayCompare comme une fonction d'ordre supérieur pour utiliser notre comparateur de premier ordre dans le contexte d'un autre type de données (Tableau).


Lâche "de comparaison 1519530920"

nous pourrions tout aussi facilement définir arrayLooseEqual en utilisant un == à la place. Maintenant, en comparant 1 (nombre) à '1' (chaîne), le résultat sera true ...

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

comparaison en Profondeur (récursif)

vous avez probablement remarqué que ce n'est qu'une comparaison superficielle tho. La solution de Tomáš est sûrement "la bonne façon™" parce qu'elle fait une comparaison profonde implicite, non ?

Eh bien, notre procédure arrayCompare est assez polyvalente pour être utilisée d'une manière qui rend un test d'égalité en profondeur un jeu d'enfant ...

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

aussi Simple que ça. Nous construisons un comparateur profond en utilisant une autre fonction d'ordre supérieur. Cette fois, nous emballons arrayCompare en utilisant un comparateur personnalisé qui vérifiera si a et b sont des tableaux. Dans l'affirmative, présenter une nouvelle demande arrayDeepCompare , sinon comparer a et b au comparateur spécifié par l'utilisateur ( f ). Cela nous permet de garder le comportement de comparaison profonde séparé de la façon dont nous comparons réellement les éléments individuels. Ie, comme l'exemple ci-dessus montre, nous pouvons comparer en profondeur en utilisant equal , looseEqual , ou tout autre comparateur que nous faisons.

parce que arrayDeepCompare est courbé, nous pouvons l'appliquer partiellement comme nous l'avons fait dans les exemples précédents aussi

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

pour moi, ce déjà une nette amélioration par rapport à la solution de Tomáš parce que je peux explicitement choisir une comparaison peu profonde ou profonde pour mes tableaux, comme nécessaire.


comparaison D'objets (exemple)

maintenant que faire si vous avez un tableau d'objets ou quelque chose ? Peut-être voulez-vous considérer ces tableaux comme "égaux" si chaque objet a la même id valeur ...

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

aussi Simple que ça. Ici j'ai utilisé des objets vanille JS, 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 entièrement remaniée pour soutenir ce genre de test d'égalité

Deep tableau avec les objets? Pas un problème. Nous avons construit des fonctions génériques très polyvalentes, donc ils fonctionneront dans une grande variété de cas d'utilisation.

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

comparaison arbitraire (exemple)

ou si vous vouliez faire une autre sorte de comparaison complètement arbitraire ? Peut-être que je veux savoir si chaque x est plus grand que chaque y ...

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

moins est plus

vous pouvez voir que nous faisons plus avec moins de code. Il n'y a rien de compliqué dans arrayCompare lui-même et chacun des comparateurs personnalisés que nous avons fait ont un très simple application.

avec facilité, nous pouvons définir exactement comment nous voulons que deux tableaux soient comparés - superficiel, profond, strict, lâche, une propriété d'objet, ou quelque calcul arbitraire, ou une combinaison de ceux - ci - tous en utilisant une procédure , arrayCompare . Peut-être même imaginer un comparateur RegExp ! Je sais comment les enfants aiment ces regexps ...

est-ce le plus rapide? Nope. Mais il n'a probablement pas besoin de l'être. Si la vitesse de est la seule métrique utilisée pour mesurer la qualité de notre code, beaucoup de vraiment grand code serait jeté loin - C'est pourquoi j'appelle cette approche le chemin pratique . Ou peut-être pour être plus juste, A chemin pratique. Cette description convient à cette réponse parce que je ne dis pas que cette réponse est seulement pratique en comparaison d'une autre réponse; elle est objectivement vraie. Nous avons atteint un haut degré de praticité avec très peu de code c'est très facile de raisonner sur. 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 au tour de et de de décider. Et personne d'autre ne peut le faire pour vous; que vous savez quels sont vos besoins. Dans presque tous les cas, je préfère le code simple, pratique et polyvalent au code intelligent et rapide. Ce que vous estimez peut différer, alors choisissez ce qui vous convient.


Modifier

mon ancienne réponse était plus axée sur la décomposition de arrayEqual en procédures minuscules. C'est un exercice intéressant, mais pas vraiment le meilleur (le plus pratique) façon d'aborder ce problème. Si vous êtes intéressé, vous pouvez voir cet historique de révision.

42
répondu user633183 2018-04-18 13:34:59

en me basant sur la réponse de Tomáš Zato, je suis d'accord sur le fait qu'il est le plus rapide de passer à travers les matrices. En outre (comme d'autres ont déjà déclaré), la fonction devrait ê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 similarité - c. - à-d. qu'ils ont les mêmes éléments, mais hors de l'ordre-pour l'usage personnel, et j'ai pensé que je lancerais ici pour que tout le monde voit.

Array.prototype.equals = function (array, strict) {
    if (!array)
        return false;

    if (arguments.length == 1)
        strict = true;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        if (this[i] instanceof Array && array[i] instanceof Array) {
            if (!this[i].equals(array[i], strict))
                return false;
        }
        else if (strict && this[i] != array[i]) {
            return false;
        }
        else if (!strict) {
            return this.sort().equals(array.sort(), true);
        }
    }
    return true;
}

cette fonction prend paramètre supplémentaire de strict qui est par défaut à true. Ce paramètre strict définit si les tableaux doivent être entièrement égaux dans les deux contenus et l'ordre de ces contenus, ou tout simplement contenir le même contenu.

exemple:

var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3];  // Loosely equal to 1
var arr3 = [2, 2, 3, 4];  // Not equal to 1
var arr4 = [1, 2, 3, 4];  // Strictly equal to 1

arr1.equals(arr2);         // false
arr1.equals(arr2, false);  // true
arr1.equals(arr3);         // false
arr1.equals(arr3, false);  // false
arr1.equals(arr4);         // true
arr1.equals(arr4, false);  // true

j'ai aussi écrit un jsfiddle rapide avec la fonction et cet exemple:

http://jsfiddle.net/Roundaround/DLkxX /

27
répondu Evan Steinkerchner 2013-07-31 20:25:14

dans l'esprit de la question initiale:

j'aimerais comparer deux tableaux... idéalement, efficacement . rien Fantaisie , juste vrai si elles sont identiques, et faux si non.

j'ai effectué des tests de performance sur quelques-unes des suggestions les plus simples proposées ici avec les résultats (fast to slow):

alors que (67%) par Tim Down

var i = a1.length;
while (i--) {
    if (a1[i] !== a2[i]) return false;
}
return true

every (69%) par utilisateur2782196

a1.every((v,i)=> v === a2[i]);

réduire (74%) "1519130920

a1.reduce((a, b) => a && a2.includes(b), true);

join & toString (78%) par Gaizka Allende & vivek

a1.join('') === a2.join('');

a1.toString() === a2.toString();

half toString (90%) par Victor Palomo

a1 == a2.toString();

stringify (100%) par radtek

JSON.stringify(a1) === JSON.stringify(a2);

Note les exemples ci-dessous supposent que les tableaux sont triés, des tableaux unidimensionnels. .length la comparaison a été supprimée pour un benchmark commun (ajouter a1.length === a2.length à l'une des suggestions et vous obtiendrez une augmentation de ~10% de la performance). Choisissez les solutions qui fonctionnent le mieux pour vous connaissant la vitesse et la limitation de chacun.

sans rapport note: il est intéressant de voir les gens obtenir tout déclencheur-heureux John Waynes sur le bouton de vote en bas sur des réponses parfaitement légitimes à cette question.

25
répondu unitario 2017-05-23 12:26:43

sur les mêmes lignes que JSON.encode doit utiliser join ().

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    //slice so we do not effect the original
    //sort makes sure they are in order
    //join makes it a string so we can do a string compare
    var cA = arrA.slice().sort().join(","); 
    var cB = arrB.slice().sort().join(",");

    return cA===cB;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];  //will return true

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //true

seul problème est si vous vous souciez des types qui les derniers tests de comparaison. Si vous vous souciez des types, vous devrez boucle.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;

    //slice so we do not effect the orginal
    //sort makes sure they are in order
    var cA = arrA.slice().sort(); 
    var cB = arrB.slice().sort();

    for(var i=0;i<cA.length;i++){
         if(cA[i]!==cB[i]) return false;
    }

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

Si l'ordre doit rester le même, que c'est juste une boucle, pas de tri est nécessaire.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    for(var i=0;i<arrA.length;i++){
         if(arrA[i]!==arrB[i]) return false;
    }

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,a) );  //true
console.log( checkArrays(a,b) );  //false
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false
6
répondu epascarello 2013-03-21 22:26:37

pour un tableau de dimension simple vous pouvez simplement utiliser:

arr1.sort().toString() == arr2.sort().toString()

cela prendra également en charge le tableau avec un index non apparié.

5
répondu Vivek 2013-09-25 09:28:57

si vous utilisez un cadre de test comme Mocha avec la Chai assertion library, vous pouvez utiliser deep equality pour comparer des tableaux.

expect(a1).to.deep.equal(a2)

ceci ne doit retourner vrai que si les tableaux ont des éléments égaux aux indices correspondants.

5
répondu metakermit 2015-06-30 03:59:00

S'il s'agit de deux tableaux de nombres ou de chaînes de caractères seulement, il s'agit d'une ligne rapide

const array1 = [1, 2, 3];
const array2 = [1, 3, 4];
console.log(array1.join(',') === array2.join(',')) //false

const array3 = [1, 2, 3];
const array4 = [1, 2, 3];
console.log(array3.join(',') === array4.join(',')) //true
5
répondu Gaizka Allende 2017-06-12 11:48:14

même si cela a beaucoup de réponses, une que je crois être d'aide:

const newArray = [ ...new Set( [...arr1, ...arr2] ) ]

il n'est pas indiqué dans la question comment la structure du tableau va ressembler, donc si vous savez avec certitude que vous ne sera pas imbriqué tableaux ou objets dans votre tableau (il m'est arrivé, c'est pourquoi je suis venu à cette réponse) le code ci-dessus fonctionnera.

ce qui se passe, c'est que nous utilisons l'opérateur spread ( ... ) concat à la fois tableaux, puis nous utilisons Set pour éliminer les doublons. Une fois que vous avez que vous pouvez comparer leurs tailles, si tous les trois tableaux ont la même taille, vous êtes bon pour aller.

Cette réponse aussi ignore l'ordre des éléments , comme je l'ai dit, la situation exacte qui m'est arrivé, peut-être que quelqu'un dans la même situation pourrait se retrouver ici (comme je l'ai fait).


Edit 1.

répondant à Dmitry Grinko question: "Pourquoi avez-vous utilisé spread operator ( ... ) ici - ...nouveau Jeu ? Il ne fonctionne pas"

considérez ce code:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

, Vous obtiendrez

[ Set { 'a', 'b', 'c' } ]

pour travailler avec cette valeur, vous devez utiliser certaines propriétés (voir https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set ). D'autre part, lorsque vous utilisez ce code:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

, Vous obtiendrez

[ 'a', 'b', 'c' ]

c'est la différence, le premier me donnerait un ensemble, ça marcherait 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 à la résolution.

5
répondu Jeferson Euclides 2017-11-10 11:24:35

Herer ma solution:

/**
 * Tests two data structures for equality
 * @param {object} x
 * @param {object} y
 * @returns {boolean}
 */
var equal = function(x, y) {
    if (typeof x !== typeof y) return false;
    if (x instanceof Array && y instanceof Array && x.length !== y.length) return false;
    if (typeof x === 'object') {
        for (var p in x) if (x.hasOwnProperty(p)) {
            if (typeof x[p] === 'function' && typeof y[p] === 'function') continue;
            if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false;
            if (typeof x[p] !== typeof y[p]) return false;
            if (typeof x[p] === 'object' && typeof y[p] === 'object') { if (!equal(x[p], y[p])) return false; } else
            if (x[p] !== y[p]) return false;
        }
    } else return x === y;
    return true;
};

fonctionne avec n'importe quelle structure de données imbriquée, et ignore évidemment les méthodes des objets. Ne pense même pas à étendre L'objet.prototype avec cette méthode, quand j'ai essayé cette fois, jQuery cassé ;)

pour la plupart des tableaux, il est encore 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.

3
répondu Harry 2013-04-10 10:38:29

nous pourrions le faire de la manière fonctionnelle, en utilisant every ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every )

function compareArrays(array1, array2) {
    if (array1.length === array2.length)
        return array1.every((a, index) => a === array2[index])
    else
        return false
}

// test
var a1 = [1,2,3];
var a2 = [1,2,3];

var a3 = ['a', 'r', 'r', 'a', 'y', '1']
var a4 = ['a', 'r', 'r', 'a', 'y', '2']

console.log(compareArrays(a1,a2)) // true
console.log(compareArrays(a1,a3)) // false
console.log(compareArrays(a3,a4)) // false
3
répondu peonicles 2015-11-10 18:39:25

compare 2 tableaux non triés:

function areEqual(a, b) {
  if ( a.length != b.length) {
    return false;
  }
  return a.filter(function(i) {
    return !b.includes(i);
  }).length === 0;  
}
3
répondu Nathan Boolean Trujillo 2017-03-01 21:28:16
var a1 = [1,2,3,6];
var a2 = [1,2,3,5];

function check(a, b) {
  return (a.length != b.length) ? false : 
  a.every(function(row, index) {
    return a[index] == b[index];
  });
}  

check(a1, a2);

////// OU ///////

var a1 = [1,2,3,6];
var a2 = [1,2,3,6];

function check(a, b) {
  return (a.length != b.length) ? false : 
  !(a.some(function(row, index) {
    return a[index] != b[index];
  }));
}  

check(a1, a2)
2
répondu Vasanth 2017-03-08 14:40:02

Extension de Tomáš Zato idée. Le tableau de Tomas.prototype.comparer devrait être en fait appelé tableau.prototype.compareIdentical.

Il passe sur:

[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 2]]) === false;
[1, "2,3"].compareIdentical ([1, 2, 3]) === false;
[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].compareIdentical ([1, 2, 1, 2]) === true;

Mais échoue sur:

[[1, 2, [3, 2]],1, 2, [3, 2]].compareIdentical([1, 2, [3, 2],[1, 2, [3, 2]]])

Voici la meilleure version (à mon avis):

Array.prototype.compare = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time
    if (this.length != array.length)
        return false;

    this.sort();
    array.sort();
    for (var i = 0; i < this.length; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].compare(array[i]))
                return false;
        }
        else if (this[i] != array[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}

http://jsfiddle.net/igos/bcfCY /

1
répondu Igor S. 2013-06-05 15:37:44

ce script compare les Objets, les Tableaux et tableau multidimensionnel

function compare(a,b){
     var primitive=['string','number','boolean'];
     if(primitive.indexOf(typeof a)!==-1 && primitive.indexOf(typeof a)===primitive.indexOf(typeof b))return a===b;
     if(typeof a!==typeof b || a.length!==b.length)return false;
     for(i in a){
          if(!compare(a[i],b[i]))return false;
     }
     return true;
}
La première ligne de

vérifie si c'est un type primitif. si donc il compare les deux paramètres.

s'il s'agit d'objets. il itère sur L'objet et vérifie chaque élément de façon récurrente.

Utilisation:

var a=[1,2,[1,2]];
var b=[1,2,[1,2]];
var isEqual=compare(a,b);  //true
1
répondu Omar Elawady 2015-04-06 18:11:25

cette fonction compare deux tableaux de forme et de dimésionalité arbitraires:

function equals(a1, a2) {

    if (!Array.isArray(a1) || !Array.isArray(a2)) {
        throw new Error("Arguments to function equals(a1, a2) must be arrays.");
    }

    if (a1.length !== a2.length) {
        return false;
    }

    for (var i=0; i<a1.length; i++) {
        if (Array.isArray(a1[i]) && Array.isArray(a2[i])) {
            if (equals(a1[i], a2[i])) {
                continue;
            } else {
                return false;
            }
        } else {
            if (a1[i] !== a2[i]) {
                return false;
            }
        }
    }

    return true;
}
1
répondu chessweb 2015-04-17 19:21:13

la raison est que l'identité ou l'opérateur strict (===), il se compare avec aucune conversion de type, ce qui signifie que si les deux valeurs n'ont pas la même valeur et le même type, ils ne seront pas considérés égaux.

regardez ce lien, il vous prend hors de doute moyen facile de comprendre comment l'identité de l'opérateur travaille

1
répondu ludico8 2015-10-22 03:57:29

choisir chacun de [a] et boucle à travers tout de [b]: Résultat: 1, 5

var a = [1,4,5,9];
var b = [1,6,7,5];

for (i = 0; i < a.length; i++) {
    for (z = 0; z < a.length; z++) {
        if (a[i] === b[z]) {
            console.log(b[z]); // if match > console.log it 
        }
    }
}
1
répondu jclobro 2017-06-07 15:45:41
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

C'est comme ça que je l'ai fait.

1
répondu Leed 2017-11-24 18:36:29

Comparer 2 tableaux:

var arr1 = [1,2,3];
var arr2 = [1,2,3];

function compare(arr1,arr2)
{
  if((arr1 == arr2) && (arr1.length == arr2.length))
    return true;
  else
    return false;
}

fonction d'appel

var isBool = compare(arr1.sort().join(),arr2.sort().join());
1
répondu Amay Kulkarni 2018-03-13 10:12:46

ma solution compare des objets, pas des tableaux. Cela fonctionnerait de la même manière que les Tomáš car les tableaux sont des objets, mais sans avertissement:

Object.prototype.compare_to = function(comparable){

    // Is the value being compared an object
    if(comparable instanceof Object){

        // Count the amount of properties in @comparable
        var count_of_comparable = 0;
        for(p in comparable) count_of_comparable++;

        // Loop through all the properties in @this
        for(property in this){

            // Decrements once for every property in @this
            count_of_comparable--;

            // Prevents an infinite loop
            if(property != "compare_to"){

                // Is the property in @comparable
                if(property in comparable){

                    // Is the property also an Object
                    if(this[property] instanceof Object){

                        // Compare the properties if yes
                        if(!(this[property].compare_to(comparable[property]))){

                            // Return false if the Object properties don't match
                            return false;
                        }
                    // Are the values unequal
                    } else if(this[property] !== comparable[property]){

                        // Return false if they are unequal
                        return false;
                    }
                } else {

                    // Return false if the property is not in the object being compared
                    return false;
                }
            }
        }
    } else {

        // Return false if the value is anything other than an object
        return false;
    }

    // Return true if their are as many properties in the comparable object as @this
    return count_of_comparable == 0;
}

espérons que cela vous aidera, vous ou toute autre personne à la recherche d'une réponse.

0
répondu user1877408 2013-10-20 03:02:53
function compareArrays(arrayA, arrayB) {
    if (arrayA.length != arrayB.length) return true;
    for (i = 0; i < arrayA.length; i++)
        if (arrayB.indexOf(arrayA[i]) == -1) {
            return true;
        }
    }
    for (i = 0; i < arrayB.length; i++) {
        if (arrayA.indexOf(arrayB[i]) == -1) {
            return true;
        }
    }
    return false;
}
0
répondu macki 2014-02-20 04:21:36

si le tableau est simple et l'ordre est matière donc ces deux lignes peuvent aider

//Assume
var a = ['a','b', 'c']; var b = ['a','e', 'c'];  

if(a.length !== b.length) return false;
return !a.reduce(
  function(prev,next,idx, arr){ return prev || next != b[idx] },false
); 

réduire les promenades à travers l'un des réseaux et renvoie 'false' si au moins un élément de 'a' n'est pas équivalent à l'élément de'b' Il suffit de l'envelopper dans la fonction

0
répondu Serge 2014-04-18 14:32:01

Voici une version CoffeeScript, pour ceux qui préfèrent cela:

Array.prototype.equals = (array) ->
  return false if not array # if the other array is a falsy value, return
  return false if @length isnt array.length # compare lengths - can save a lot of time

  for item, index in @
    if item instanceof Array and array[index] instanceof Array # Check if we have nested arrays
      if not item.equals(array[index]) # recurse into the nested arrays
        return false
    else if this[index] != array[index]
      return false # Warning - two different object instances will never be equal: {x:20} != {x:20}
  true

tous les crédits vont à @tomas-zato.

0
répondu Martin 2014-04-30 10:17:24

dans mon cas, les tableaux comparés ne contiennent que des nombres et des chaînes. Cette fonction vous indiquera si les tableaux contiennent les mêmes éléments.

function are_arrs_match(arr1, arr2){
    return arr1.sort().toString() === arr2.sort().toString()
}

essayons!

arr1 = [1, 2, 3, 'nik']
arr2 = ['nik', 3, 1, 2]
arr3 = [1, 2, 5]

console.log (are_arrs_match(arr1, arr2)) //true
console.log (are_arrs_match(arr1, arr3)) //false
0
répondu yesnik 2016-08-10 09:21:43

bien que la meilleure réponse à cette question soit correcte et bonne, le code fourni pourrait être amélioré.

ci-dessous est mon propre code pour comparer des tableaux et des objets. Le code est court et simple:

Array.prototype.equals = function(otherArray) {
  if (!otherArray || this.length != otherArray.length) return false;
  return this.reduce(function(equal, item, index) {
    var otherItem = otherArray[index];
    var itemType = typeof item, otherItemType = typeof otherItem;
    if (itemType !== otherItemType) return false;
    return equal && (itemType === "object" ? item.equals(otherItem) : item === otherItem);
  }, true);
};

if(!Object.prototype.keys) {
  Object.prototype.keys = function() {
    var a = [];
    for (var key in this) {
      if (this.hasOwnProperty(key)) a.push(key);
    }
    return a;
  }
  Object.defineProperty(Object.prototype, "keys", {enumerable: false});
}

Object.prototype.equals = function(otherObject) {
  if (!otherObject) return false;
  var object = this, objectKeys = object.keys();
  if (!objectKeys.equals(otherObject.keys())) return false;
  return objectKeys.reduce(function(equal, key) {
    var value = object[key], otherValue = otherObject[key];
    var valueType = typeof value, otherValueType = typeof otherValue;
    if (valueType !== otherValueType) return false;
    // this will call Array.prototype.equals for arrays and Object.prototype.equals for objects
    return equal && (valueType === "object" ? value.equals(otherValue) : value === otherValue);
  }, true);
}
Object.defineProperty(Object.prototype, "equals", {enumerable: false});

ce code supporte les tableaux imbriqués dans des objets et des objets imbriqués dans des tableaux.

vous pouvez voir une suite complète de tests et tester le code vous-même à cette repl: https://repl.it/Esfz/3

0
répondu Mator 2016-12-18 03:11:52