JavaScript'te iki dizi arasındaki farkı döndürmenin bir yolu var mı?
Örneğin:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
O(a1.length x log(a2.length))
bu performans JavaScript'te mümkün müdür?
JavaScript'te iki dizi arasındaki farkı döndürmenin bir yolu var mı?
Örneğin:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
O(a1.length x log(a2.length))
bu performans JavaScript'te mümkün müdür?
Yanıtlar:
Sanırım normal bir diziyi karşılaştırıyorsunuz. Değilse, for döngüsünü for .. in loop olarak değiştirmeniz gerekir .
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"));
Daha iyi bir çözüm, geriye dönük uyumlulukla ilgilenmiyorsanız, filtre kullanmaktır. Ama yine de, bu çözüm işe yarıyor.
var a1 = ['a', 'b'];
ve var a2 = ['a', 'b', 'c', 'd', 'b'];
, bunun yanlış cevap dönecektir yani ['c', 'd', 'b']
yerine ['c', 'd']
.
function diff2(a, b) { var i, la = a.length, lb = b.length, res = []; if (!la) return b; else if (!lb) return a; for (i = 0; i < la; i++) { if (b.indexOf(a[i]) === -1) res.push(a[i]); } for (i = 0; i < lb; i++) { if (a.indexOf(b[i]) === -1) res.push(b[i]); } return res; }
ES7 kullanmanın daha iyi bir yolu var:
kesişim
let intersection = arr1.filter(x => arr2.includes(x));
Bunun için [1,2,3] [2,3]
verim olacaktır [2,3]
. Öte yandan, [1,2,3] [2,3,5]
aynı şeyi geri getirecektir.
fark
let difference = arr1.filter(x => !arr2.includes(x));
Bunun için [1,2,3] [2,3]
verim olacaktır [1]
. Öte yandan, [1,2,3] [2,3,5]
aynı şeyi geri getirecektir.
Bir İçin simetrik fark , bunu yapabilirsiniz:
let difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
Bu şekilde, arr1 öğesinde olmayan arr1 öğelerinin tüm öğelerini içeren bir dizi alırsınız.
@Joshaven Potter'ın cevabına işaret ettiği gibi, bunu Array.prototype'e ekleyebilirsiniz, böylece şu şekilde kullanılabilir:
Array.prototype.diff = function(arr2) { return this.filter(x => !arr2.includes(x)); }
[1, 2, 3].diff([2, 3])
< 0
yerine== -1
Array
fark bir sözde olduğu set operation
Özellik arama çok kendi iştir çünkü, Set
daha hızlı daha sonra büyüklüklerdir s, indexOf
/ includes
. Basitçe söylemek gerekirse, çözümünüz çok verimsiz ve oldukça yavaş.
Set
değerler benzersiz olmak zorunda, değil mi?
[1,2,3] [2,3,5]
Numaraların benzersiz olduğu göz önüne alındığında işe yarayacağını anladım , ancak söylemiş [1,1,2,3] [1,2,3,5]
ve beklemiş [1]
olsaydınız kullanamazsınız Set
. Çözümünüz de işe yaramayacaktı: - / Bu işlevi yarattım, çünkü daha özlü bir şekilde yapmanın tatmin edici bir yolunu bulamadım. Bunun nasıl yapılacağı hakkında herhangi bir fikriniz varsa, bilmek isterim!
Array.includes()
yerine ES6 ait ES7 özelliği? (1) (2) - ve devam etmek için ES6 ile Array.some()
örneğin kullanabilirsiniz let intersection = aArray.filter(a => bArray.some(b => a === b))
, hayır?
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"]
Not indexOf ve filtre, yani ie9'dan önce kullanılamaz.
[1,2,3].diff([3,4,5])
o dönecektir [1,2]
yerine [1,2,4,5]
orijinal söz konusu sorunu çözmezse, böylece bir şey farkında olmak.
Bu, jQuery kullanarak tam olarak aradığınız sonucu almanın en kolay yoludur:
var diff = $(old_array).not(new_array).get();
diff
şimdi ne içeriyor old_array
o değilnew_array
.not
diziyle kullandığınızda, jQuery, .grep()
dizileri filtrelemek için özel olarak yerleşik yardımcı programını kullanır . Bunun değiştiğini göremiyorum.
Alt çizgi'deki fark yöntemi (veya onun yerine bırakılan Lo-Dash ) bunu da yapabilir:
(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]
Herhangi bir Alt Çizgi işlevinde olduğu gibi, bunu daha nesne yönelimli bir tarzda da kullanabilirsiniz:
_([1, 2, 3, 4, 5]).difference([5, 2, 10]);
"Fark" için iki olası yorum vardır. Hangisini istediğini seçmene izin vereceğim. Diyelim ki:
var a1 = ['a', 'b' ];
var a2 = [ 'b', 'c'];
Almak istiyorsanız ['a']
, bu işlevi kullanın:
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;
}
Eğer almak istiyorsanız ['a', 'c']
(tüm unsurları içerdiği ya a1
ya a2
, ancak ikisini - sözde simetrik fark ), bu işlevi kullanın:
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 kullanıyorsanız _.difference(a1, a2)
(yukarıdaki 1. durum) veya _.xor(a1, a2)
(2. durum) kullanabilirsiniz.
Underscore.js kullanıyorsanız, _.difference(a1, a2)
durum 1'in işlevini .
Yukarıdaki kod tüm tarayıcılarda çalışır. Bununla birlikte, yaklaşık 10.000'den fazla öğeden oluşan büyük diziler için, oldukça yavaş olur, çünkü O (n²) karmaşıklığına sahiptir. Birçok modern tarayıcıda, Set
işleri hızlandırmak için ES6 nesnesinden yararlanabiliriz. Lodash Set
mevcut olduğunda otomatik olarak kullanılır. Lodash kullanmıyorsanız, Axel Rauschmayer'in blog gönderisinden esinlenerek aşağıdaki uygulamayı kullanın :
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));
}
-0, +0, NaN veya seyrek dizileri önemsiyorsanız tüm örneklerin davranışı şaşırtıcı veya açık olmayabilir . (Çoğu kullanım için bu önemli değil.)
Simetrik farkı elde etmek için dizileri her iki şekilde (veya birden çok dizi olması durumunda tüm yollarla) karşılaştırmanız gerekir.
// diff between just two arrays:
function arrayDiff(a, b) {
return [
...a.filter(x => !b.includes(x)),
...b.filter(x => !a.includes(x))
];
}
// diff between multiple arrays:
function arrayDiff(...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter(x => !unique.includes(x));
}));
}
// diff between just two arrays:
function arrayDiff(a, b) {
return [
...a.filter(x => b.indexOf(x) === -1),
...b.filter(x => a.indexOf(x) === -1)
];
}
// diff between multiple arrays:
function arrayDiff(...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter(x => unique.indexOf(x) === -1);
}));
}
// diff between just two arrays:
function arrayDiff(a, b) {
var arrays = Array.prototype.slice.call(arguments);
var diff = [];
arrays.forEach(function(arr, i) {
var other = i === 1 ? a : b;
arr.forEach(function(x) {
if (other.indexOf(x) === -1) {
diff.push(x);
}
});
})
return diff;
}
// diff between multiple arrays:
function arrayDiff() {
var arrays = Array.prototype.slice.call(arguments);
var diff = [];
arrays.forEach(function(arr, i) {
var others = arrays.slice(0);
others.splice(i, 1);
var otherValues = Array.prototype.concat.apply([], others);
var unique = otherValues.filter(function (x, j) {
return otherValues.indexOf(x) === j;
});
diff = diff.concat(arr.filter(x => unique.indexOf(x) === -1));
});
return diff;
}
Misal:
// diff between two arrays:
const a = ['a', 'd', 'e'];
const b = ['a', 'b', 'c', 'd'];
arrayDiff(a, b); // (3) ["e", "b", "c"]
// diff between multiple arrays
const a = ['b', 'c', 'd', 'e', 'g'];
const b = ['a', 'b'];
const c = ['a', 'e', 'f'];
arrayDiff(a, b, c); // (4) ["c", "d", "g", "f"]
function arrayDiffByKey(key, ...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter( x =>
!unique.some(y => x[key] === y[key])
);
}));
}
Misal:
const a = [{k:1}, {k:2}, {k:3}];
const b = [{k:1}, {k:4}, {k:5}, {k:6}];
const c = [{k:3}, {k:5}, {k:7}];
arrayDiffByKey('k', a, b, c); // (4) [{k:2}, {k:4}, {k:6}, {k:7}]
ES6'da daha temiz bir yaklaşım aşağıdaki çözümdür.
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
a2.filter(d => !a1.includes(d)) // gives ["c", "d"]
a2.filter(d => a1.includes(d)) // gives ["a", "b"]
[ ...a2.filter(d => !a1.includes(d)),
...a1.filter(d => !a2.includes(d)) ]
a1 = ['a', 'b', 'e']
: e çıkartılmayacak.
Bu durumda bir Set kullanabilirsiniz . Bu tür bir işlem için optimize edilmiştir (birleşim, kavşak, fark).
Yinelemelere izin vermediğinde, durumunuz için geçerli olduğundan emin olun.
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}
Set
Her şeyi almak zorunda kalmadan sadece işlevi indiremediğiniz ne yazık !
function diff(a1, a2) {
return a1.concat(a2).filter(function(val, index, arr){
return arr.indexOf(val) === arr.lastIndexOf(val);
});
}
Her iki diziyi birleştirdiğinizde, benzersiz değerler yalnızca bir kez görünür, böylece indexOf (), lastIndexOf () ile aynı olur.
bir diziyi diğerinden çıkarmak için aşağıdaki snippet'i kullanmanız yeterlidir:
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;
});
İkincisi olmayan ilk dizinin öğeleri olan ['1,' 2 ',' 6 '] değerini döndürür.
Bu nedenle, sorun örneğinize göre, aşağıdaki kod tam çözümdür:
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;
});
ES6'nın setler ve uyarıcı operatörü ile gelmesiyle (sadece Firefox'ta çalışırken, uyumluluk tablosunu kontrol edin ), aşağıdaki bir astarı yazabilirsiniz:
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)))];
sonuçlanacak [ "c", "d" ]
.
b.filter(x => !a.indexOf(x)))
O(n + m)
çözümdür O(n * m)
. Uzun listeler al ve çözümüm saniyeler içinde çalışacak, seninki ise saatler sürecek.
a.filter(x => !b1.has(x))
daha basit. Ve spesifikasyonun sadece karmaşıklığın ortalama n * f(m) + m
olarak alt f(m)
doğrusal ile olmasını gerektirdiğini unutmayın . Bundan daha iyi n * m
, ama ille de değil n + m
.
var difference = [...new Set([...a].filter(x => !b1.has(x)))];
Neden yinelenen 'a' dizisi oluşturuyorsunuz? Neden filtrenin sonucunu bir kümeye, sonra tekrar diziye dönüştürüyorsunuz? Bu eşdeğer değilvar difference = a.filter(x => !b1.has(x));
Bilgisayar difference
arasında iki diziler biridir Set
operasyonlar. Terim Set
, arama hızını artırmak için yerel türün kullanılması gerektiğini zaten belirtir . Her neyse, iki set arasındaki farkı hesapladığınızda üç permütasyon vardır:
[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]
İşte bu permütasyonları yansıtan fonksiyonel bir çözüm.
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) );
difference
:differencer
önemsizdir. Sadece differencel
ters çevrilmiş argümanlarla. Kolaylık sağlamak için bir işlev yazabilirsiniz:const differencer = flip(differencel)
. Bu kadar!
difference
:Şimdi sol ve sağ difference
olana sahibiz, simetrik uygulamak da önemsiz:
// small, reusable auxiliary functions
const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const concat = y => xs => xs.concat(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);
};
// symmetric difference
const difference = ys => xs =>
concat(differencel(xs) (ys)) (flip(differencel) (xs) (ys));
// 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( difference(xs) (ys) );
Sanırım bu örnek, fonksiyonel programlamanın ne anlama geldiğini görmek için iyi bir başlangıç noktasıdır:
Birçok farklı şekilde birbirine takılabilen yapı taşlarıyla programlama.
indexOf()
Küçük diziler için bir çözüm uygun olacaktır, ancak uzunlukları büyüdükçe algoritmanın performansı yaklaşmaktadır O(n^2)
. Dizi girişlerini anahtar olarak saklamak için ilişkilendirilebilir diziler olarak nesneleri kullanarak çok büyük diziler için daha iyi performans gösteren bir çözüm; yinelenen girişleri de otomatik olarak ortadan kaldırır, ancak yalnızca dize değerleriyle (veya dize olarak güvenli bir şekilde saklanabilen değerlerle) çalışır:
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']
Joshaven Potter'ın yukarıdaki cevabı harika. Ancak, B dizisindeki C dizisinde olmayan, ancak tersi olmayan öğeleri döndürür. Örneğin, var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
o zaman çıktı alır: ==> [1,2,6]
, ama değil [1,2,6,7]
, bu ikisi arasındaki gerçek fark. Yine de yukarıda Potter'ın kodunu kullanabilirsiniz, ancak karşılaştırmayı bir kez daha geriye doğru tekrarlayabilirsiniz:
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);
Bu çıktı: [ 1, 2, 6, 7 ]
Sorunu çözmenin başka bir yolu
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]
Ayrıca, ok işlevi sözdizimini kullanabilirsiniz:
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]
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]
difference
gelecekteki bir sürümde işlev olarak tanıtılırsa ve bu işlev sizinkinden farklı bir işlev imzasına sahipse, bu işlevi kullanan kodunuzu veya yabancı kitaplıkları bozacaktır.
JavaScript'in filtre işleviyle Çok Basit Çözüm:
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);
Buna ne dersin:
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));
Böylece bu şekilde array1.diff(array2)
farklarını elde etmek için yapabilirsiniz (Algoritmanın korkunç zaman karmaşıklığı olsa - O (dizi1.length x dizi2.length) inanıyorum)
Http://phrogz.net/JS/ArraySetMath.js kullanarak şunları yapabilirsiniz:
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"]
function diffArray(arr1, arr2) {
var newArr = arr1.concat(arr2);
return newArr.filter(function(i){
return newArr.indexOf(i) == newArr.lastIndexOf(i);
});
}
bu benim için çalışıyor
filter
)fn
Dizi öğelerinin nasıl karşılaştırılacağını belirlemenizi sağlayan isteğe bağlı geri arama parametresifunction 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(', ')
);
length
değerlerine gerek yok. Zaten düz mülkiyet. jsperf.com/array-length-caching
Bu işe yarıyor: temel olarak iki diziyi birleştirin, yinelenenleri arayın ve çoğaltılamayanı fark olan yeni bir diziye itin.
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;
}
// es6 yaklaşımı
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
}
başka bir cevap, ama kimse jsperf bahsetmiş gibi görünüyor birkaç algoritmaları ve teknoloji desteği karşılaştırmak nerede: https://jsperf.com/array-difference-javascript filtre kullanarak görünüyor en iyi sonucu alır. Teşekkürler
Sadece düşünmek ... bir meydan okuma uğruna ;-) bu işe yarayacaktır ... (dize, sayı vb. Temel diziler için) iç içe diziler yok
function diffArrays(arr1, arr2, returnUnion){
var ret = [];
var test = {};
var bigArray, smallArray, key;
if(arr1.length >= arr2.length){
bigArray = arr1;
smallArray = arr2;
} else {
bigArray = arr2;
smallArray = arr1;
}
for(var i=0;i<bigArray.length;i++){
key = bigArray[i];
test[key] = true;
}
if(!returnUnion){
//diffing
for(var i=0;i<smallArray.length;i++){
key = smallArray[i];
if(!test[key]){
test[key] = null;
}
}
} else {
//union
for(var i=0;i<smallArray.length;i++){
key = smallArray[i];
if(!test[key]){
test[key] = true;
}
}
}
for(var i in test){
ret.push(i);
}
return ret;
}
array1 = "test1", "test2","test3", "test4", "test7"
array2 = "test1", "test2","test3","test4", "test5", "test6"
diffArray = diffArrays(array1, array2);
//returns ["test5","test6","test7"]
diffArray = diffArrays(array1, array2, true);
//returns ["test1", "test2","test3","test4", "test5", "test6","test7"]
Sıralama büyük olasılıkla yukarıda belirtildiği gibi olmayacaktır ... ancak istenirse diziyi sıralamak için .sort () yöntemini çağırın.
Eski bir dizi ve yeni bir dizi aldı ve bana bir dizi öğe ve kaldırılan öğelerin bir dizi verdi benzer bir işlev istedim ve verimli olmasını istedim (yani hiçbir .contains!).
Önerilen çözümümle buradan oynayabilirsiniz: http://jsbin.com/osewu3/12 .
Bu algoritmada herhangi bir sorun / iyileştirme görebilen var mı? Teşekkürler!
Kod listesi:
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};
}
Farklı kütüphanelerin kullanılmasını gerektirmeyen basit bir cevap arıyordum ve burada bahsetmediğimi düşündüğüm bir cevap buldum. Ne kadar verimli veya hiçbir şey bilmiyorum ama işe yarıyor;
function find_diff(arr1, arr2) {
diff = [];
joined = arr1.concat(arr2);
for( i = 0; i <= joined.length; i++ ) {
current = joined[i];
if( joined.indexOf(current) == joined.lastIndexOf(current) ) {
diff.push(current);
}
}
return diff;
}
Kodum için de çıkarılmış kopyaları gerekir, ama sanırım bu her zaman tercih edilmez.
Sanırım ana dezavantajı, potansiyel olarak zaten reddedilen birçok seçeneği karşılaştırıyor olmasıdır.
en iyi cevap için küçük bit düzeltme
function arr_diff(a1, a2)
{
var a=[], diff=[];
for(var i=0;i<a1.length;i++)
a[a1[i]]=a1[i];
for(var i=0;i<a2.length;i++)
if(a[a2[i]]) delete a[a2[i]];
else a[a2[i]]=a2[i];
for(var k in a)
diff.push(a[k]);
return diff;
}
bu, geçerli eleman tipini dikkate alacaktır. b / c [a1 [i]] yaptığımızda, bir değeri orojinal değerinden dizeye dönüştürür, böylece gerçek değeri kaybettik.