Hoe u het verschil kunt krijgen tussen twee arrays in JavaScript?

Is er een manier om het verschil tussen twee arrays in JavaScript te retourneren?

Bijvoorbeeld:

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

1, Autoriteit 100%

Ik neem aan dat u een normale array vergelijkt. Zo niet, dan moet u de voor lus wijzigen in een voor .. in lus.

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"));

2, Autoriteit 756%

Er is een betere manier met ES7:


kruising

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

Voor [1,2,3] [2,3]Het levert [2,3]op. Aan de andere kant, voor [1,2,3] [2,3,5]zal hetzelfde retourneren.


verschil

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

Voor [1,2,3] [2,3]levert het [1]op. Aan de andere kant, voor [1,2,3] [2,3,5]wordt hetzelfde geretourneerd.


Voor een symmetrisch verschilkunt u het volgende doen:

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

Op deze manier krijgt u een array met alle elementen van arr1 die niet in arr2 staan en omgekeerd

Zoals @Joshaven Potter in zijn antwoord opmerkte, kun je dit toevoegen aan Array.prototype zodat het als volgt kan worden gebruikt:

Array.prototype.diff = function(arr2) { return this.filter(x => !arr2.includes(x)); }
[1, 2, 3].diff([2, 3])

Antwoord 3, autoriteit 92%

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"]

Antwoord 4, autoriteit 90%

Dit is verreweg de gemakkelijkste manier om precies het resultaat te krijgen waarnaar u op zoek bent, met jQuery:

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

diffbevat nu wat in old_arraystond en niet in new_array


Antwoord 5, autoriteit 63%

De verschilmethode in Underscore(of de drop-in vervanging, Lo-Dash) kan dit ook:

(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]

Zoals bij elke Underscore-functie, kunt u deze ook in een meer objectgeoriënteerde stijl gebruiken:

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

Antwoord 6, autoriteit 32%

Gewoon JavaScript

Er zijn twee mogelijke interpretaties voor “verschil”. Ik laat je kiezen welke je wilt. Stel dat je het volgende hebt:

var a1 = ['a', 'b'     ];
var a2 = [     'b', 'c'];
  1. Als je ['a']wilt krijgen, gebruik dan deze functie:

    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. Als u ['a', 'c'](alle elementen in ofwela1of a2, maar niet beide — het zogenaamde symmetrische verschil), gebruik deze functie:

    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

Als je lodash gebruikt, kun je _.difference(a1, a2)gebruiken (geval 1 hierboven) of _.xor(a1, a2)(geval 2).

Als u Underscore.js gebruikt, kunt u de _.difference(a1, a2)functie voor geval 1.

ES6 Set, voor zeer grote arrays

De bovenstaande code werkt in alle browsers. Voor grote arrays van meer dan ongeveer 10.000 items wordt het echter vrij traag, omdat het O(n²) complexiteit heeft. In veel moderne browsers kunnen we profiteren van de ES6 Setobject in om dingen te versnellen. Lodash gebruikt automatisch Setwanneer het beschikbaar is. Als je geen lodash gebruikt, gebruik dan de volgende implementatie, geïnspireerd door Axel Rauschmayer’s blog bericht:

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));
}

Opmerkingen

Het gedrag voor alle voorbeelden kan verrassend of niet duidelijk zijn als u om -0, +0, nan of dunne arrays. (Voor de meeste toepassingen doet dit niet uit.)


7, Autoriteit 23%

Een schonere aanpak in ES6 is de volgende oplossing.

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

verschil

a2.filter(d => !a1.includes(d)) // gives ["c", "d"]

kruising

a2.filter(d => a1.includes(d)) // gives ["a", "b"]

Disjunctive Union (symmetrisch verschil)

[ ...a2.filter(d => !a1.includes(d)),
  ...a1.filter(d => !a2.includes(d)) ]

Antwoord 8, autoriteit 12%

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

Voeg beide arrays samen, unieke waarden verschijnen slechts één keer, dus indexOf() zal hetzelfde zijn als lastIndexOf().


Antwoord 9, autoriteit 10%

Met de komst van ES6 met sets en splat-operator (werkt momenteel alleen in Firefox, controleer compatibiliteitstabel), kunt u de volgende oneliner schrijven:

var a = ['a', 'b', 'c', 'd'];
var b = ['a', 'b'];
var b1 = new Set(b);
var difference = [...new Set(a.filter(x => !b1.has(x)))];

wat resulteert in [ "c", "d" ].


Antwoord 10, autoriteit 7%

om de ene array van de andere af te trekken, gebruik je het onderstaande fragment:

var a1 = ['1','2','3','4','6'];
var a2 = ['3','4','5'];
var items = new Array();
items = jQuery.grep(a1,function (item) {
    return jQuery.inArray(item, a2) < 0;
});

Het retourneert [‘1,’2′,’6’] die items van de eerste array zijn die niet bestaan in de tweede.

Daarom, volgens uw probleemvoorbeeld, is de volgende code de exacte oplossing:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];
var _array = new Array();
_array = jQuery.grep(array2, function (item) {
     return jQuery.inArray(item, array1) < 0;
});

Antwoord 11, autoriteit 6%

Functionele aanpak met ES2015

Het differencetussen twee arrays berekenen is een van de Set-bewerkingen. De term geeft al aan dat het native type Setmoet worden gebruikt om de opzoeksnelheid te verhogen. Hoe dan ook, er zijn drie permutaties als je het verschil tussen twee sets berekent:

[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]

Hier is een functionele oplossing die deze permutaties weerspiegelt.

Links difference:

// small, reusable auxiliary functions
const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// left difference
const differencel = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? false
     : true
  ) (xs);
};
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
// run the computation
console.log( differencel(xs) (ys) );

Antwoord 12, autoriteit 6%

Een andere manier om het probleem op te lossen

function diffArray(arr1, arr2) {
    return arr1.concat(arr2).filter(function (val) {
        if (!(arr1.includes(val) && arr2.includes(val)))
            return val;
    });
}
diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]);    // return [7, 4, 5]

U kunt ook de syntaxis van de pijlfunctie gebruiken:

const diffArray = (arr1, arr2) => arr1.concat(arr2)
    .filter(val => !(arr1.includes(val) && arr2.includes(val)));
diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]);    // return [7, 4, 5]

Antwoord 13, autoriteit 4%

Een oplossing die indexOf()gebruikt, is oké voor kleine arrays, maar naarmate ze langer worden, benadert de prestatie van het algoritme O(n^2). Hier is een oplossing die beter presteert voor zeer grote arrays door objecten als associatieve arrays te gebruiken om de array-items als sleutels op te slaan; het elimineert ook automatisch dubbele invoer, maar werkt alleen met tekenreekswaarden (of waarden die veilig als tekenreeksen kunnen worden opgeslagen):

function arrayDiff(a1, a2) {
  var o1={}, o2={}, diff=[], i, len, k;
  for (i=0, len=a1.length; i<len; i++) { o1[a1[i]] = true; }
  for (i=0, len=a2.length; i<len; i++) { o2[a2[i]] = true; }
  for (k in o1) { if (!(k in o2)) { diff.push(k); } }
  for (k in o2) { if (!(k in o1)) { diff.push(k); } }
  return diff;
}
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
arrayDiff(a1, a2); // => ['c', 'd']
arrayDiff(a2, a1); // => ['c', 'd']

Antwoord 14, autoriteit 4%

Het bovenstaande antwoord van Joshaven Potter is geweldig. Maar het retourneert elementen in array B die niet in array C staan, maar niet andersom. Bijvoorbeeld, als var a=[1,2,3,4,5,6].diff( [3,4,5,7]);dan zal het resultaat geven: ==> [1,2,6], maar niet[1,2,6,7], wat het werkelijke verschil tussen de twee is. Je kunt nog steeds de bovenstaande code van Potter gebruiken, maar herhaal de vergelijking ook een keer omgekeerd:

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};
////////////////////  
// Examples  
////////////////////
var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
var b=[3,4,5,7].diff([1,2,3,4,5,6]);
var c=a.concat(b);
console.log(c);

Dit moet geven: [ 1, 2, 6, 7 ]


15, Autoriteit 3%

Zeer eenvoudige oplossing met de filter functie van JavaScript:

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
function diffArray(arr1, arr2) {
  var newArr = [];
  var myArr = arr1.concat(arr2);
    newArr = myArr.filter(function(item){
      return arr2.indexOf(item) < 0 || arr1.indexOf(item) < 0;
    });
   alert(newArr);
}
diffArray(a1, a2);

16, Autoriteit 3%

Array.prototype.difference = function(e) {
    return this.filter(function(i) {return e.indexOf(i) < 0;});
};
eg:- 
[1,2,3,4,5,6,7].difference( [3,4,5] );  
 => [1, 2, 6 , 7]

17, Autoriteit 2%

Hoe zit het met dit:

Array.prototype.contains = function(needle){
  for (var i=0; i<this.length; i++)
    if (this[i] == needle) return true;
  return false;
} 
Array.prototype.diff = function(compare) {
    return this.filter(function(elem) {return !compare.contains(elem);})
}
var a = new Array(1,4,7, 9);
var b = new Array(4, 8, 7);
alert(a.diff(b));

Dus op deze manier kun je array1.diff(array2)doen om hun verschil te krijgen (vreselijke tijdscomplexiteit voor het algoritme echter – O(array1.length x array2.length) geloof ik)

p>


Antwoord 18, autoriteit 2%

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  return newArr.filter(function(i){
    return newArr.indexOf(i) == newArr.lastIndexOf(i);
  });
}

dit werkt voor mij


Antwoord 19

Met http://phrogz.net/JS/ArraySetMath.jskunt u:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];
var array3 = array2.subtract( array1 );
// ["test5", "test6"]
var array4 = array1.exclusion( array2 );
// ["test5", "test6"]

Antwoord 20

  • Pure JavaScript-oplossing (geen bibliotheken)
  • Compatibel met oudere browsers (maakt geen gebruik van filter)
  • O(n^2)
  • Optionele fncallback-parameter waarmee u kunt specificeren hoe array-items moeten worden vergeleken
function diff(a, b, fn){
    var max = Math.max(a.length, b.length);
        d = [];
    fn = typeof fn === 'function' ? fn : false
    for(var i=0; i < max; i++){
        var ac = i < a.length ? a[i] : undefined
            bc = i < b.length ? b[i] : undefined;
        for(var k=0; k < max; k++){
            ac = ac === undefined || (k < b.length && (fn ? fn(ac, b[k]) : ac == b[k])) ? undefined : ac;
            bc = bc === undefined || (k < a.length && (fn ? fn(bc, a[k]) : bc == a[k])) ? undefined : bc;
            if(ac == undefined && bc == undefined) break;
        }
        ac !== undefined && d.push(ac);
        bc !== undefined && d.push(bc);
    }
    return d;
}
alert(
    "Test 1: " + 
    diff(
        [1, 2, 3, 4],
        [1, 4, 5, 6, 7]
      ).join(', ') +
    "\nTest 2: " +
    diff(
        [{id:'a',toString:function(){return this.id}},{id:'b',toString:function(){return this.id}},{id:'c',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
        [{id:'a',toString:function(){return this.id}},{id:'e',toString:function(){return this.id}},{id:'f',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
        function(a, b){ return a.id == b.id; }
    ).join(', ')
);

Antwoord 21

Ik wilde een vergelijkbare functie die een oude array en een nieuwe array innam en me een array van toegevoegde items en een array van verwijderde items gaf, en ik wilde dat het efficiënt was (dus geen .bevat!).

p>

Je kunt hier met mijn voorgestelde oplossing spelen: http://jsbin.com/osewu3/12.

Kan iemand problemen/verbeteringen aan dat algoritme zien? Bedankt!

Codelijst:

function diff(o, n) {
  // deal with empty lists
  if (o == undefined) o = [];
  if (n == undefined) n = [];
  // sort both arrays (or this won't work)
  o.sort(); n.sort();
  // don't compare if either list is empty
  if (o.length == 0 || n.length == 0) return {added: n, removed: o};
  // declare temporary variables
  var op = 0; var np = 0;
  var a = []; var r = [];
  // compare arrays and add to add or remove lists
  while (op < o.length && np < n.length) {
      if (o[op] < n[np]) {
          // push to diff?
          r.push(o[op]);
          op++;
      }
      else if (o[op] > n[np]) {
          // push to diff?
          a.push(n[np]);
          np++;
      }
      else {
          op++;np++;
      }
  }
  // add remaining items
  if( np < n.length )
    a = a.concat(n.slice(np, n.length));
  if( op < o.length )
    r = r.concat(o.slice(op, o.length));
  return {added: a, removed: r}; 
}

Antwoord 22

U kunt underscore.js gebruiken: http://underscorejs.org/#intersection

Je hebt methoden nodig voor array:

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

Antwoord 23

Dit werkt: voeg in feite de twee arrays samen, zoek naar de duplicaten en duw wat niet is gedupliceerd in een nieuwe array, wat het verschil is.

function diff(arr1, arr2) {
  var newArr = [];
  var arr = arr1.concat(arr2);
  for (var i in arr){
    var f = arr[i];
    var t = 0;
    for (j=0; j<arr.length; j++){
      if(arr[j] === f){
        t++; 
        }
    }
    if (t === 1){
      newArr.push(f);
        }
  } 
  return newArr;
}

Antwoord 24

//es6 benadering

function diff(a, b) {
  var u = a.slice(); //dup the array
  b.map(e => {
    if (u.indexOf(e) > -1) delete u[u.indexOf(e)]
    else u.push(e)   //add non existing item to temp array
  })
  return u.filter((x) => {return (x != null)}) //flatten result
}

Antwoord 25

Symmetrischeen lineaire complexiteit. Vereist ES6.

function arrDiff(arr1, arr2) {
    var arrays = [arr1, arr2].sort((a, b) => a.length - b.length);
    var smallSet = new Set(arrays[0]);
    return arrays[1].filter(x => !smallSet.has(x));
}

Antwoord 26

nog een ander antwoord, maar het lijkt erop dat niemand jsperf noemde waar ze verschillende algoritmen en technologische ondersteuning vergelijken: https:/ /jsperf.com/array-difference-javascriptlijkt het gebruik van filter de beste resultaten te geven. bedankt


Antwoord 27

Gebruik hiervoor extra geheugen. Op die manier kun je het oplossen met minder tijdscomplexiteit, O(n) in plaats van o(n*n).

function getDiff(arr1,arr2){
let k = {};
let diff = []
arr1.map(i=>{
    if (!k.hasOwnProperty(i)) {
        k[i] = 1
    }
}
)
arr2.map(j=>{
    if (!k.hasOwnProperty(j)) {
        k[j] = 1;
    } else {
        k[j] = 2;
    }
}
)
for (var i in k) {
    if (k[i] === 1)
        diff.push(+i)
}
return diff
}
getDiff([4, 3, 52, 3, 5, 67, 9, 3],[4, 5, 6, 75, 3, 334, 5, 5, 6])

Antwoord 28

Om het verschilvan 2 arrays zonder duplicaten te vinden:

function difference(arr1, arr2){
  let setA = new Set(arr1);
  let differenceSet = new Set(arr2.filter(ele => !setA.has(ele)));
  return [...differenceSet ];
}

1 difference([2,2,3,4],[2,3,3,4])oplevert []

2 difference([1,2,3],[4,5,6])oplevert [4,5,6]

3. difference([1,2,3,4],[1,2])oplevert []

4 difference([1,2],[1,2,3,4])oplevert [3,4]

Opmerking: De bovenstaande oplossing vereist dat u altijd de grotere serie te sturen als de tweede parameter. Om de absolute verschil te vinden, moet u eerst de grotere reeks van de twee en dan het vinden van werk op hen.

Om de absolute verschil van 2 arrays zonder duplicaten te vinden:

function absDifference(arr1, arr2){
  const {larger, smaller} = arr1.length > arr2.length ? 
  {larger: arr1, smaller: arr2} : {larger: arr2, smaller: arr1}
  let setA = new Set(smaller);
  let absDifferenceSet = new Set(larger.filter(ele => !setA.has(ele)));
  return [...absDifferenceSet ];
}

1 absDifference([2,2,3,4],[2,3,3,4])oplevert []

2 absDifference([1,2,3],[4,5,6])oplevert [4,5,6]

3. absDifference([1,2,3,4],[1,2])oplevert [3,4]

4 absDifference([1,2],[1,2,3,4])oplevert [3,4]

Voorbeeld 3 Beide oplossingen

Other episodes