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"]
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"]
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.
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.
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é.
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"));
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.
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.
@Batman Oui, mais seulement s'ils sont des références à la même objet ( {a: 1} != {a: 1}
) ( preuve )
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.
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.
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]);
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.
Attention, cette implémentation ne fonctionnera pas pour les tableaux d'objets. Voir stackoverflow.com/q/8672383/14731 pour plus d'informations.
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().
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}
Ç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...
Set est également implémenté dans google closure. fermeture-library.googlecode.com/svn/docs/
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.
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 ?0 votes
Vérifiez ma bibliothèque, elle peut vous aider, @netilon/differify est l'une des bibliothèques diff les plus rapides pour la comparaison d'objets/de tableaux : npmjs.com/package/@netilon/differify