1391 votes

Comment obtenir la différence entre deux tableaux en JavaScript ?

Existe-t-il un moyen de renvoyer la différence entre deux tableaux en JavaScript ?

Par exemple :

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];

// need ["c", "d"]

13 votes

Symétrique ou non symétrique ?

2 votes

Avec la nouvelle fonction ES6, cela peut être fait comme un simple one liner (cela prendra beaucoup de temps pour pouvoir être utilisé dans tous les principaux navigateurs). Dans tous les cas, consultez mon réponse

1 votes

Un aspect important de la solution est la performance. la complexité temporelle asymptotique de ce type d'opération - dans d'autres langages - est de O(a1.length x log(a2.length)) - Cette performance est-elle possible en JavaScript ?

959voto

Joshaven Potter Points 2458
Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

//////////////
// Examples //
//////////////

const dif1 = [1,2,3,4,5,6].diff( [3,4,5] );  
console.log(dif1); // => [1, 2, 6]

const dif2 = ["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);  
console.log(dif2); // => ["test5", "test6"]

Note .indexOf() y .filter() ne sont pas disponibles avant IE9.

1 votes

Vous pouvez également trouver utile tutoriel de montage

55 votes

Le seul navigateur important qui ne prend pas en charge filter et indexOf est IE8. IE9 les supporte tous les deux. Ce n'est donc pas une erreur.

16 votes

Ie7 et ie8 sont toujours (malheureusement) très pertinents, mais vous pouvez trouver du code polyfill pour les deux fonctions sur le site MDN : developer.mozilla.org/fr/JavaScript/Référence/Global_Objects/ developer.mozilla.org/fr/JavaScript/Référence/Global_Objects/ Chargez dans le code listé sous "compatabilité" via un conditionnel IE & BOOM. Ie7/8 est supporté.

387voto

Thinker Points 7239

Cette réponse a été écrite en 2009, elle est donc un peu dépassée, mais elle est aussi assez pédagogique pour comprendre le problème. La meilleure solution que j'utiliserais aujourd'hui serait

let difference = arr1.filter(x => !arr2.includes(x));

(crédits à l'autre auteur ici)

Je suppose que vous comparez un tableau normal. Si ce n'est pas le cas, vous devez modifier le pour à une boucle pour dans boucle.

function arr_diff (a1, a2) {

    var a = [], diff = [];

    for (var i = 0; i < a1.length; i++) {
        a[a1[i]] = true;
    }

    for (var i = 0; i < a2.length; i++) {
        if (a[a2[i]]) {
            delete a[a2[i]];
        } else {
            a[a2[i]] = true;
        }
    }

    for (var k in a) {
        diff.push(k);
    }

    return diff;
}

console.log(arr_diff(['a', 'b'], ['a', 'b', 'c', 'd']));
console.log(arr_diff("abcd", "abcde"));
console.log(arr_diff("zxc", "zxc"));

67 votes

Cela peut fonctionner, mais il faut trois boucles pour accomplir ce qui peut être fait en une ligne de code en utilisant la méthode de filtrage de Array.

13 votes

Juste pour être clair, ceci implémente la fonction différence symétrique de a1 y a2 contrairement aux autres réponses postées ici.

0 votes

Cela reste pertinent si vous devez prendre en charge IE8, qui ne dispose pas du filtre

313voto

superphonic Points 2176

C'est de loin le moyen le plus simple d'obtenir exactement le résultat que vous recherchez, en utilisant jQuery :

var diff = $(old_array).not(new_array).get();

diff contient maintenant ce qui était dans old_array qui n'est pas dans new_array

4 votes

@Batman Oui, mais seulement s'ils sont des références à la même objet ( {a: 1} != {a: 1} ) ( preuve )

0 votes

Est-il possible de l'utiliser avec des tableaux contenant les données d'un objet personnalisé ? J'ai essayé de la même manière mais cela n'a pas fonctionné. Toute idée sera très appréciée.

10 votes

Est-ce une astuce ? Le site doc considère cette méthode comme faisant partie de la Méthodes pour les éléments du DOM et non comme une aide générale pour les tableaux. Ainsi, il pourrait fonctionner de cette façon maintenant, mais peut-être pas dans les versions futures, car il n'était pas prévu de l'utiliser de cette façon. Cependant, je serais heureux s'il devenait officiellement une aide générale pour les tableaux.

179voto

mahemoff Points 4879

La méthode de la différence dans Underscore (ou son remplaçant, Lo-Dash ) peuvent aussi le faire :

(R)eturns the values from array that are not present in the other arrays

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

Comme pour toute fonction Underscore, vous pouvez également l'utiliser dans un style plus orienté objet :

_([1, 2, 3, 4, 5]).difference([5, 2, 10]);

4 votes

Je pense que c'est une bonne solution du point de vue des performances, d'autant plus que lodash et underscore se disputent sans cesse la meilleure implémentation. De plus, elle est compatible avec IE6.

4 votes

Attention, cette implémentation ne fonctionnera pas pour les tableaux d'objets. Voir stackoverflow.com/q/8672383/14731 pour plus d'informations.

1 votes

Comme le mentionne l'une des réponses, cela fonctionne s'il s'agit du même objet, mais pas si deux objets ont les mêmes propriétés. Je pense que c'est correct, car les notions d'égalité varient (par exemple, il pourrait aussi s'agir d'un attribut "id" dans certaines applications). Cependant, il serait bon que vous puissiez passer un test de comparaison à intersect().

55voto

Samuel Carrijo Points 9056

Vous pourriez utiliser un Définir dans ce cas. Il est optimisé pour ce type d'opération (union, intersection, différence).

Assurez-vous qu'il s'applique à votre cas, une fois qu'il n'autorise aucun doublon.

var a = new JS.Set([1,2,3,4,5,6,7,8,9]);
var b = new JS.Set([2,4,6,8]);

a.difference(b)
// -> Set{1,3,5,7,9}

4 votes

Ça a l'air d'être une belle bibliothèque ! C'est dommage que l'on ne puisse pas télécharger seulement les fichiers de la bibliothèque. Set fonction sans avoir à obtenir tout le reste...

0 votes

@Blixt je crois que vous pouvez tout télécharger, et inclure juste le fichier set.js

0 votes

Set est également implémenté dans google closure. fermeture-library.googlecode.com/svn/docs/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X