Question Comment faire la différence entre deux tableaux en Javascript?


Est-il possible de retourner la différence entre deux tableaux en JavaScript?

Par exemple:

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

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

Tout conseil grandement apprécié.


452
2017-07-27 10:38


origine


Réponses:


Je suppose que vous comparez un tableau normal. Si non, vous devez changer le pour boucle à un 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"));

Une meilleure solution, si vous ne vous souciez pas de la compatibilité ascendante, consiste à utiliser le filtre. Mais encore, cette solution fonctionne.


150
2017-07-27 11:20



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

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

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

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

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

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

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


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

Remarque indexOf et filter ne sont pas disponibles en ie avant ie9.


746
2017-10-26 18:34



Il y a un meilleur moyen d'utiliser ES7:

Intersection

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

Intersection difference Venn Diagram

Pour [1,2,3] [2,3] ça va céder [2,3]. Par contre, pour [1,2,3] [2,3,5] va retourner la même chose.

Différence

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

Right difference Venn Diagram

Pour [1,2,3] [2,3] ça va céder [1]. Par contre, pour [1,2,3] [2,3,5] va retourner la même chose.

Pour un différence symétrique, tu peux faire:

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

Symmetric difference Venn Diagram

De cette façon, vous obtiendrez un tableau contenant tous les éléments de arr1 qui ne sont pas dans arr2 et vice-versa

Comme l'a souligné @Joshaven Potter dans sa réponse, vous pouvez ajouter ceci à Array.prototype afin qu'il puisse être utilisé comme ceci:

Array.prototype.diff = arr1.filter(x => arr2.includes(x));
[1, 2, 3].diff([2, 3])

424
2017-10-09 09:33



C'est de loin le moyen le plus facile 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 en old_array ce n'est pas dans new_array


289
2018-03-13 12:57



La méthode de différence dans Underscore (ou son remplacement, Lo-Dash) peut le faire aussi:

(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 avec n'importe quelle fonction Underscore, vous pouvez également l'utiliser dans un style plus orienté objet:

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

138
2017-07-05 22:44



Plain JavaScript

Il y a deux interprétations possibles pour "différence". Je vais vous laisser choisir celui que vous voulez. Dites que vous avez:

var a1 = ['a', 'b'     ];
var a2 = [     'b', 'c'];
  1. Si vous voulez obtenir ['a'], utilisez cette fonction:

    function difference(a1, a2) {
      var result = [];
      for (var i = 0; i < a1.length; i++) {
        if (a2.indexOf(a1[i]) === -1) {
          result.push(a1[i]);
        }
      }
      return result;
    }
    
  2. Si vous voulez obtenir ['a', 'c'] (tous les éléments contenus dans non plus  a1 ou a2, mais pas les deux - les soi-disant différence symétrique), utilisez cette fonction:

    function symmetricDifference(a1, a2) {
      var result = [];
      for (var i = 0; i < a1.length; i++) {
        if (a2.indexOf(a1[i]) === -1) {
          result.push(a1[i]);
        }
      }
      for (i = 0; i < a2.length; i++) {
        if (a1.indexOf(a2[i]) === -1) {
          result.push(a2[i]);
        }
      }
      return result;
    }
    

Lodash / Underscore

Si vous utilisez lodash, vous pouvez utiliser _.difference(a1, a2) (cas 1 ci-dessus) ou _.xor(a1, a2) (cas 2).

Si vous utilisez Underscore.js, vous pouvez utiliser le _.difference(a1, a2) fonction pour le cas 1.

ES6 Set, pour les très grandes baies

Le code ci-dessus fonctionne sur tous les navigateurs. Cependant, pour les grands tableaux de plus de 10 000 éléments, il devient assez lent, car il présente une complexité O (n²). Sur de nombreux navigateurs modernes, nous pouvons profiter de l'ES6 Set objet pour accélérer les choses. Lodash utilise automatiquement Set quand il est disponible Si vous n'utilisez pas lodash, utilisez l'implémentation suivante, inspirée par Le blogue d'Axel Rauschmayer:

function difference(a1, a2) {
  var a2Set = new Set(a2);
  return a1.filter(function(x) { return !a2Set.has(x); });
}

function symmetricDifference(a1, a2) {
  return difference(a1, a2).concat(difference(a2, a1));
}

Remarques

Le comportement de tous les exemples peut être surprenant ou non évident si vous vous souciez de -0, +0, NaN ou des tableaux épars. (Pour la plupart des utilisations, cela n'a pas d'importance.)


59
2018-05-17 16:01



Vous pourriez utiliser un Ensemble 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 ne permet pas de doublons.

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}

31
2017-07-27 10:43



function diff(a1, a2) {
  return a1.concat(a2).filter(function(val, index, arr){
    return arr.indexOf(val) === arr.lastIndexOf(val);
  });
}

Fusionner les deux tableaux, les valeurs uniques n'apparaîtront qu'une seule fois, donc indexOf () sera identique à lastIndexOf ().


23
2018-06-30 14:33