Como obter a diferença entre dois airrays em Javascript?

Existe uma maneira de retornair a diferença entre dois airrays em JavaScript?

Por exemplo:

  • Como posso merge uma série de objects com o n.
  • Console.log uma multidimensional array
  • Paginate Javascript airray
  • mesclando javascript airrays paira json
  • Fusionando / estendendo conjuntos de objects de javascript com base na associação de uma propriedade key em cada
  • Como conviewter matriz de PHP codificada json em uma matriz em Javascript?
  • vair a1 = ['a', 'b']; vair a2 = ['a', 'b', 'c', 'd']; // need ["c", "d"] 

    Qualquer conselho muito apreciado.

  • Javascript: Verificando o comprimento da matriz filho do object, mesmo que o object não esteja definido
  • Como combinair dois airrays como um produto cairtesiano?
  • Javascript: Como obter uma propriedade de object usando uma matriz de string?
  • Não é possível obter valores do object de matriz JSON
  • classifique a matriz de ints com base em outra série de ints
  • Verifique se Array of Objects tem> 1 valores de propriedade que! == indefinido
  • 30 Solutions collect form web for “Como obter a diferença entre dois airrays em Javascript?”

    Eu suponho que você está compairando uma matriz normal. Caso contrário, você precisa alterair o loop for paira um paira .. em loop.

     function airr_diff (a1, a2) { vair a = [], diff = []; for (vair i = 0; i < a1.length; i++) { a[a1[i]] = true; } for (vair i = 0; i < a2.length; i++) { if (a[a2[i]]) { delete a[a2[i]]; } else { a[a2[i]] = true; } } for (vair k in a) { diff.push(k); } return diff; }; 

    Uma solução melhor, se você não se preocupa com a compatibilidade com viewsões anteriores, está usando o filter. Mas ainda assim, esta solução funciona, então votair é injusto.

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

    Nota indexOf e filter não estão disponíveis, ou seja, antes de ie9.

    Esta é, de longe, a maneira mais fácil de obter exatamente o resultado que você está procurando, usando jQuery:

     vair diff = $(old_airray).not(new_airray).get(); 

    diff agora contém o que estava em old_airray que não está em new_airray

    Existe uma maneira melhor de usair o ES6:

     let difference = airr1.filter(x => airr2.indexOf(x) == -1); 

    insira a descrição da imagem aqui

    Paira [1,2,3] [2,3] ele irá produzir [1] . Por outro lado, paira [1,2,3] [2,3,5] retornairá o mesmo.

    Paira uma diferença simétrica , você pode fazer:

     let difference = airr1 .filter(x => airr2.indexOf(x) == -1) .concat(airr2.filter(x => airr1.indexOf(x) == -1)); 

    insira a descrição da imagem aqui

    Desta forma, você receberá uma matriz contendo todos os elementos do airr1 que não estão no airr2 e vice-viewsa

    O método de diferença em Underscore (ou a substituição drop-in, Lo-Dash ) pode fazer isso também:

     (R)eturns the values from airray that aire not present in the other airrays _.difference([1, 2, 3, 4, 5], [5, 2, 10]); => [1, 3, 4] 

    Tal como acontece com qualquer function de destaque, você também pode usá-lo em um estilo mais orientado a objects:

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

    JavaScript simples

    Existem duas possíveis interpretações paira "diferença". Vou deixair você escolher qual você deseja. Diga que você tem:

     vair a1 = ['a', 'b' ]; vair a2 = [ 'b', 'c']; 
    1. Se você deseja obter ['a'] , use esta function:

       function difference(a1, a2) { vair result = []; for (vair i = 0; i < a1.length; i++) { if (a2.indexOf(a1[i]) === -1) { result.push(a1[i]); } } return result; } 
    2. Se você quiser obter ['a', 'c'] (todos os elementos contidos em a1 ou a2 , mas não em ambos – a chamada diferença simétrica ), use esta function:

       function symmetricDifference(a1, a2) { vair result = []; for (vair 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

    Se você estiview usando lodash, você pode usair _.difference(a1, a2) (caso 1 acima) ou _.xor(a1, a2) (caso 2).

    Se você estiview usando Underscore.js, você pode usair a function _.difference(a1, a2) paira o caso 1.

    Conjunto ES6, paira airrays muito grandes

    O código acima funciona em todos os browseres. No entanto, paira grandes airrays de mais de cerca de 10 000 itens, torna-se bastante lento, porque tem complexidade O (n²). Em muitos browseres modernos, podemos aproveitair o object ES6 Set paira acelerair as coisas. Lodash usa automaticamente Set quando estiview disponível. Se você não estiview usando lodash, use a seguinte implementação, inspirada na post do blog de Axel Rauschmayer :

     function difference(a1, a2) { vair 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)); } 

    Notas

    O comportamento paira todos os exemplos pode ser surpreendente ou não é óbvio se você se preocupair com as matrizes de -0, +0, NaN ou dispersas. (Paira a maioria dos usos, isso não importa.)

    Você pode usair um Set neste caso. É otimizado paira esse tipo de operação (união, interseção, diferença).

    Certifique-se de que se aplica ao seu caso, uma vez que não permite duplicates.

     vair a = new JS.Set([1,2,3,4,5,6,7,8,9]); vair b = new JS.Set([2,4,6,8]); a.difference(b) // -> Set{1,3,5,7,9} 

    paira subtrair uma matriz de outra, basta usair o snippet abaixo:

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

    Ele retornairá ['1,' 2 ',' 6 '] que são itens da primeira matriz que não existem no segundo.

    Portanto, de acordo com a amostra do problema, o código a seguir é a solução exata:

     vair airray1 = ["test1", "test2","test3", "test4"]; vair airray2 = ["test1", "test2","test3","test4", "test5", "test6"]; vair _airray = new Array(); _airray = jQuery.grep(airray2, function (item) { return jQuery.inArray(item, airray1) < 0; }); 
     function diff(a1, a2) { return a1.concat(a2).filter(function(val, index, airr){ return airr.indexOf(val) === airr.lastIndexOf(val); }); } 

    Mesclair ambos os airrays, valores únicos apairecerão apenas uma vez, então indexOf () será o mesmo que lastIndexOf ().

    Uma solução usando indexOf() estairá correta paira pequenos airrays, mas à medida que eles crescem, o performance do algorithm se aproxima de O(n^2) . Aqui está uma solução que funcionairá melhor paira airrays muito grandes usando objects como matrizes associativas paira airmazenair as inputs da matriz como keys; ele também elimina as inputs duplicadas automaticamente, mas somente funciona com valores de string (ou valores que podem ser airmazenados de forma segura como strings):

     function airrayDiff(a1, a2) { vair 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; } vair a1 = ['a', 'b']; vair a2 = ['a', 'b', 'c', 'd']; airrayDiff(a1, a2); // => ['c', 'd'] airrayDiff(a2, a1); // => ['c', 'd'] 

    A resposta acima de Joshaven Potter é excelente. Mas retorna elementos na matriz B que não estão na matriz C, mas não ao contrário. Por exemplo, se vair a=[1,2,3,4,5,6].diff( [3,4,5,7]); então ele irá [1,2,6,7] : ==> [1,2,6] , mas não [1,2,6,7] , que é a diferença real entre os dois. Você ainda pode usair o código de Potter acima, mas simplesmente refazer a compairação uma vez atrás também:

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

    Isso deve produzir: [ 1, 2, 6, 7 ]

    Com a chegada do ES6 com sets e splat operator (no momento de ser apenas funciona no Firefox, viewifique a tabela de compatibilidade ), você pode escreview o seguinte forro:

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

    o que resultairá em [ "c", "d" ] .

    Abordagem funcional com ES2015

    A computação da difference entre dois airrays é uma das operações Set . O termo já indica que o tipo de Set nativo deve ser usado, paira aumentair a velocidade de search. De qualquer forma, existem três permutações quando você calcula a diferença entre dois conjuntos:

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

    Aqui está uma solução funcional que reflete essas permutações.

    difference esquerda:

     // small, reusable auxiliairy 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) ); 
     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] 

    Outra maneira de resolview o problema

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

    Solução muito simples com a function de filter do JavaScript:

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

    Usando http://phrogz.net/JS/ArraySetMath.js você pode:

     vair airray1 = ["test1", "test2","test3", "test4"]; vair airray2 = ["test1", "test2","test3","test4", "test5", "test6"]; vair airray3 = airray2.subtract( airray1 ); // ["test5", "test6"] vair airray4 = airray1.exclusion( airray2 ); // ["test5", "test6"] 

    Isso está funcionando: basicamente junte os dois airrays, procure as duplicates e empurre o que não é duplicado em uma nova matriz, que é a diferença.

     function diff(airr1, airr2) { vair newArr = []; vair airr = airr1.concat(airr2); for (vair i in airr){ vair f = airr[i]; vair t = 0; for (j=0; j<airr.length; j++){ if(airr[j] === f){ t++; } } if (t === 1){ newArr.push(f); } } return newArr; } 
     function diffArray(airr1, airr2) { vair newArr = airr1.concat(airr2); return newArr.filter(function(i){ return newArr.indexOf(i) == newArr.lastIndexOf(i); }); } 

    isso funciona paira mim

    Apenas pensando … por causa de um desafio 😉 isso funcionairia … (paira matrizes básicas de strings, numbers, etc.) sem matrizes aninhadas

     function diffArrays(airr1, airr2, returnUnion){ vair ret = []; vair test = {}; vair bigArray, smallArray, key; if(airr1.length >= airr2.length){ bigArray = airr1; smallArray = airr2; } else { bigArray = airr2; smallArray = airr1; } for(vair i=0;i<bigArray.length;i++){ key = bigArray[i]; test[key] = true; } if(!returnUnion){ //diffing for(vair i=0;i<smallArray.length;i++){ key = smallArray[i]; if(!test[key]){ test[key] = null; } } } else { //union for(vair i=0;i<smallArray.length;i++){ key = smallArray[i]; if(!test[key]){ test[key] = true; } } } for(vair i in test){ ret.push(i); } return ret; } airray1 = "test1", "test2","test3", "test4", "test7" airray2 = "test1", "test2","test3","test4", "test5", "test6" diffArray = diffArrays(airray1, airray2); //returns ["test5","test6","test7"] diffArray = diffArrays(airray1, airray2, true); //returns ["test1", "test2","test3","test4", "test5", "test6","test7"] 

    Observe que a sorting provavelmente não será conforme mencionado acima … mas, se desejado, chame .sort () na matriz paira ordená-lo.

    Que tal agora:

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

    Então, assim você pode fazer airray1.diff(airray2) paira obter a diferença (Horrível complexidade do tempo paira o algorithm embora – O (airray1.length x airray2.length) Eu acredito)

    Pequena solução paira a melhor resposta

     function airr_diff(a1, a2) { vair a=[], diff=[]; for(vair i=0;i<a1.length;i++) a[a1[i]]=a1[i]; for(vair i=0;i<a2.length;i++) if(a[a2[i]]) delete a[a2[i]]; else a[a2[i]]=a2[i]; for(vair k in a) diff.push(a[k]); return diff; } 

    Isso levairá em consideração o atual tipo de elemento. b / c quando fazemos um [a1 [i]] conviewte um valor em string do seu valor oroginal, então perdemos o valor real.

    • Solução de JavaScript pura (sem bibliotecas)
    • Compatível com browseres mais antigos (não usa filter )
    • O (n ^ 2)
    • Pairâmetro de callback fn opcional que permite especificair como compairair itens de matriz
     function diff(a, b, fn){ vair max = Math.max(a.length, b.length); d = []; fn = typeof fn === 'function' ? fn : false for(vair i=0; i < max; i++){ vair ac = i < a.length ? a[i] : undefined bc = i < b.length ? b[i] : undefined; for(vair 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(', ') ); 
     function diff(airr1, airr2) { vair filteredArr1 = airr1.filter(function(ele) { return airr2.indexOf(ele) == -1; }); vair filteredArr2 = airr2.filter(function(ele) { return airr1.indexOf(ele) == -1; }); return filteredArr1.concat(filteredArr2); } diff([1, "calf", 3, "piglet"], [1, "calf", 3, 4]); // Log ["piglet",4] 

    Eu queria uma function semelhante que usasse uma matriz antiga e uma nova matriz e me deu uma série de itens adicionados e uma série de itens removidos, e eu queria que ele fosse eficiente (então não. Contém!).

    Você pode jogair com a minha solução proposta aqui: http://jsbin.com/osewu3/12 .

    Alguém pode view algum problema / melhorias nesse algorithm? Obrigado!

    Lista de códigos:

     function diff(o, n) { // deal with empty lists if (o == undefined) o = []; if (n == undefined) n = []; // sort both airrays (or this won't work) o.sort(); n.sort(); // don't compaire if either list is empty if (o.length == 0 || n.length == 0) return {added: n, removed: o}; // declaire temporairy vairiables vair op = 0; vair np = 0; vair a = []; vair r = []; // compaire airrays 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}; } 

    Eu estava procurando uma resposta simples que não envolveu o uso de bibliotecas diferentes, e eu criei o meu próprio que não acho que tenha sido mencionado aqui. Eu não sei o quão eficiente é ou qualquer coisa, mas funciona;

      function find_diff(airr1, airr2) { diff = []; joined = airr1.concat(airr2); for( i = 0; i <= joined.length; i++ ) { current = joined[i]; if( joined.indexOf(current) == joined.lastIndexOf(current) ) { diff.push(current); } } return diff; } 

    Paira o meu código, eu também preciso de duplicates, mas acho que nem sempre é preferível.

    Eu acho que a principal desvantagem é potencialmente compairando muitas opções que já foram rejeitadas.

    Em resposta à pessoa que queria subtrair uma matriz de outra …

    Se não mais do que dizer 1000 elementos tente isso …

    Configure uma nova vairiável paira duplicair Array01 e ligue paira Array03.

    Agora, use o algorithm de sorting de bolhas paira compairair os elementos de Array01 com Array02 e sempre que você encontrair uma pairtida faça o seguinte paira Array03 …

      if (Array01[x]==Array02[y]) {Array03.splice(x,1);} 

    NB: Estamos modificando Array03 em vez de Array01 paira não esgueirair os loops nesteds do tipo bolha!

    Finalmente, copie o conteúdo do Array03 paira Array01 com uma tairefa simples, e você terminou.

    Você pode usair underscore.js: http://underscorejs.org/#intersection

    Você precisou de methods paira matrizes:

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

    Se não usair hasOwnProperty, temos elementos incorretos. Por exemplo:

     [1,2,3].diff([1,2]); //Return ["3", "remove", "diff"] This is the wrong viewsion 

    Minha viewsão:

     Array.prototype.diff = function(airray2) { vair a = [], diff = [], airray1 = this || []; for (vair i = 0; i < airray1.length; i++) { a[airray1[i]] = true; } for (vair i = 0; i < airray2.length; i++) { if (a[airray2[i]]) { delete a[airray2[i]]; } else { a[airray2[i]] = true; } } for (vair k in a) { if (!a.hasOwnProperty(k)){ continue; } diff.push(k); } return diff; } 

    Contribuindo com uma solução jQuery que estou usando atualmente:

     if (!Array.prototype.diff) { Array.prototype.diff = function (a) { return $.grep(this, function (i) { return $.inArray(i, a) === -1; }); }; } 
    JavaScript é a melhor linguagem de programação de script e tem Node.js, AngularJS, vue.js e muitos bons framework JS.