有没有办法返回JavaScript中两个数组之间的差?
例如:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
有没有办法返回JavaScript中两个数组之间的差?
例如:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
You can use underscore.js : http://underscorejs.org/#intersection
You have needed methods for 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]
Just thinking... for the sake of a challenge ;-) would this work... (for basic arrays of strings, numbers, etc.) no nested arrays
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"]
Note the sorting will likely not be as noted above... but if desired, call .sort() on the array to sort it.
This is working: basically merge the two arrays, look for the duplicates and push what is not duplicated into a new array which is the difference.
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;
}
Symmetric and linear complexity. Requires 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));
}
yet another answer, but seems nobody mentioned jsperf where they compare several algorithms and technology support: https://jsperf.com/array-difference-javascript seems using filter gets the best results. thanks
function diffArray(arr1, arr2) {
var newArr = arr1.concat(arr2);
return newArr.filter(function(i){
return newArr.indexOf(i) == newArr.lastIndexOf(i);
});
}
this is works for me
Using http://phrogz.net/JS/ArraySetMath.js you can:
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"]
Joshaven Potter的上述回答很棒。但是它返回的数组B中的元素不在数组C中,反之亦然。例如,如果var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
这样,它将输出:==> [1,2,6]
,但不会 输出[1,2,6,7]
,这是两者之间的实际差异。您仍然可以使用上面的Potter的代码,但是只需将比较也向后重做一次即可:
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);
这应该输出: [ 1, 2, 6, 7 ]
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]
这个怎么样:
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));
因此,您可以通过这种方式array1.diff(array2)
来获得它们的差异(尽管我相信算法的时间复杂度很差-我相信O(array1.length x array2.length)
解决问题的另一种方法
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]
另外,您可以使用箭头函数语法:
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]
function diff(a1, a2) {
return a1.concat(a2).filter(function(val, index, arr){
return arr.indexOf(val) === arr.lastIndexOf(val);
});
}
合并两个数组,唯一值将仅出现一次,因此indexOf()将与lastIndexOf()相同。
计算difference
两个数组之间的和是Set
操作之一。该术语已经表明Set
应该使用本机类型,以提高查找速度。无论如何,当您计算两组之间的差异时,存在三个排列:
[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]
这是一个反映这些排列的功能解决方案。
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
是微不足道的。它只是differencel
带有翻转的参数。为了方便起见,您可以编写一个函数:const differencer = flip(differencel)
。就这样!
difference
:现在我们有了左右一个,实现对称也difference
变得很简单:
// 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) );
我想这个例子是一个很好的起点,可以使人对函数式编程的印象:
使用可以以许多不同方式连接在一起的构件块进行编程。
在这种情况下,您可以使用Set。针对此类操作(联合,相交,差)进行了优化。
一旦不允许重复,请确保适用于您的情况。
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}
到目前为止,这是使用jQuery精确获得所需结果的最简单方法:
var diff = $(old_array).not(new_array).get();
diff
现在包含的内容old_array
不在其中new_array
Underscore(或它的替代产品Lo-Dash)中的差异方法也可以做到这一点:
(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]
与任何Underscore函数一样,您也可以以更面向对象的方式使用它:
_([1, 2, 3, 4, 5]).difference([5, 2, 10]);
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"]
注意 indexOf和filter在ie9之前的ie中不可用。
使用ES7有更好的方法:
路口
let intersection = arr1.filter(x => arr2.includes(x));
因为[1,2,3] [2,3]
它会屈服[2,3]
。另一方面,for [1,2,3] [2,3,5]
将返回相同的内容。
区别
let difference = arr1.filter(x => !arr2.includes(x));
因为[1,2,3] [2,3]
它会屈服[1]
。另一方面,for [1,2,3] [2,3,5]
将返回相同的内容。
对于对称差异,您可以执行以下操作:
let difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
这样,您将获得一个包含arr1不在arr2中的所有元素的数组,反之亦然
正如@Joshaven Potter在他的答案中指出的那样,您可以将其添加到Array.prototype中,以便可以这样使用:
Array.prototype.diff = function(arr2) { return this.filter(x => arr2.includes(x)); }
[1, 2, 3].diff([2, 3])
littlebit fix for the best answer
this will take current type of element in consideration. b/c when we make a[a1[i]] it converts a value to string from its oroginal value, so we lost actual value.