Joh*_*wan 660 javascript arrays array-difference
有没有办法在JavaScript中返回两个数组之间的差异?
例如:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
Run Code Online (Sandbox Code Playgroud)
任何建议都非常感谢.
Lui*_*ira 948
使用ES7有更好的方法:
路口
let intersection = arr1.filter(x => arr2.includes(x));
Run Code Online (Sandbox Code Playgroud)
因为[1,2,3] [2,3]它会屈服[2,3].另一方面,因为[1,2,3] [2,3,5]将返回同样的事情.
区别
let difference = arr1.filter(x => !arr2.includes(x));
Run Code Online (Sandbox Code Playgroud)
因为[1,2,3] [2,3]它会屈服[1].另一方面,因为[1,2,3] [2,3,5]将返回同样的事情.
对于对称差异,您可以:
let difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
Run Code Online (Sandbox Code Playgroud)
这样,您将获得一个包含arr1的所有元素的数组,这些元素不在arr2中,反之亦然
正如@Joshaven Potter在答案中指出的那样,你可以将它添加到Array.prototype中,这样它就可以这样使用:
Array.prototype.diff = function(arr2) { return this.filter(x => arr2.includes(x)); }
[1, 2, 3].diff([2, 3])
Run Code Online (Sandbox Code Playgroud)
Jos*_*ter 896
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"]
Run Code Online (Sandbox Code Playgroud)
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"]Run Code Online (Sandbox Code Playgroud)
注意 indexOf和filter在ie9之前不可用.
sup*_*nic 305
到目前为止,这是使用jQuery获得您正在寻找的结果的最简单方法:
var diff = $(old_array).not(new_array).get();
Run Code Online (Sandbox Code Playgroud)
diff现在包含了old_array不存在的内容new_array
Thi*_*ker 191
我假设你正在比较一个普通的数组.如果没有,则需要将for循环更改为for ... in循环.
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"));Run Code Online (Sandbox Code Playgroud)
如果您不关心向后兼容性,更好的解决方案是使用过滤器.但是,这个解决方案仍然有效.
mah*_*off 152
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]
Run Code Online (Sandbox Code Playgroud)
与任何Underscore函数一样,您也可以使用更面向对象的样式:
_([1, 2, 3, 4, 5]).difference([5, 2, 10]);
Run Code Online (Sandbox Code Playgroud)
Jo *_*iss 72
"差异"有两种可能的解释.我会让你选择你想要的那个.说你有:
var a1 = ['a', 'b' ];
var a2 = [ 'b', 'c'];
Run Code Online (Sandbox Code Playgroud)
如果你想获得['a'],请使用此功能:
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;
}
Run Code Online (Sandbox Code Playgroud)如果你想获得['a', 'c'](包含了所有的元素或者 a1还是a2,但不能同时-所谓的对称差),使用此功能:
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;
}
Run Code Online (Sandbox Code Playgroud)如果您使用的是lodash,则可以使用_.difference(a1, a2)(上面的案例1)或_.xor(a1, a2)(案例2).
如果您使用的是Underscore.js,则可以使用_.difference(a1, a2)案例1 的函数.
上面的代码适用于所有浏览器.但是,对于超过10,000个项目的大型数组,它变得非常慢,因为它具有O(n²)复杂度.在许多现代浏览器中,我们可以利用ES6 Set对象来加快速度.Lodash Set会在可用时自动使用.如果您不使用lodash,请使用以下实现,灵感来自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));
}
Run Code Online (Sandbox Code Playgroud)
如果您关心-0,+ 0,NaN或稀疏数组,所有示例的行为可能会令人惊讶或不明显.(对于大多数用途,这没关系.)
Sum*_*tra 63
ES6 中更简洁的方法是以下解决方案。
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
Run Code Online (Sandbox Code Playgroud)
a2.filter(d => !a1.includes(d)) // gives ["c", "d"]
Run Code Online (Sandbox Code Playgroud)
a2.filter(d => a1.includes(d)) // gives ["a", "b"]
Run Code Online (Sandbox Code Playgroud)
[ ...a2.filter(d => !a1.includes(d)),
...a1.filter(d => !a2.includes(d)) ]
Run Code Online (Sandbox Code Playgroud)
Luc*_*one 47
要获得对称差异,您需要以两种方式比较数组(或者在多个数组的情况下以所有方式)
// 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));
}));
}
Run Code Online (Sandbox Code Playgroud)
// 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);
}));
}
Run Code Online (Sandbox Code Playgroud)
// 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;
}
Run Code Online (Sandbox Code Playgroud)
例:
// 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"]
Run Code Online (Sandbox Code Playgroud)
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])
);
}));
}
Run Code Online (Sandbox Code Playgroud)
例:
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}]
Run Code Online (Sandbox Code Playgroud)
nki*_*tku 44
const unique = (a) => [...new Set(a)];
const uniqueBy = (x,f)=>Object.values(x.reduce((a,b)=>((a[f(b)]=b),a),{}));
const intersection = (a, b) => a.filter((v) => b.includes(v));
const diff = (a, b) => a.filter((v) => !b.includes(v));
const symDiff = (a, b) => diff(a, b).concat(diff(b, a));
const union = (a, b) => diff(a, b).concat(b);
const a = unique([1, 2, 3, 4, 5, 5]);
console.log(a);
const b = [4, 5, 6, 7, 8];
console.log(intersection(a, b), diff(a, b), symDiff(a, b), union(a, b));
console.log(uniqueBy(
[
{ id: 1, name: "abc" },
{ id: 2, name: "xyz" },
{ id: 1, name: "abc" },
],
(v) => v.id
));
const intersectionBy = (a, b, f) => a.filter((v) => b.some((u) => f(v, u)));
console.log(intersectionBy(
[
{ id: 1, name: "abc" },
{ id: 2, name: "xyz" },
],
[
{ id: 1, name: "abc" },
{ id: 3, name: "pqr" },
],
(v, u) => v.id === u.id
));
const diffBy = (a, b, f) => a.filter((v) => !b.some((u) => f(v, u)));
console.log(diffBy(
[
{ id: 1, name: "abc" },
{ id: 2, name: "xyz" },
],
[
{ id: 1, name: "abc" },
{ id: 3, name: "pqr" },
],
(v, u) => v.id === u.id
));Run Code Online (Sandbox Code Playgroud)
const unique = <T>(array: T[]) => [...new Set(array)];
const intersection = <T>(array1: T[], array2: T[]) =>
array1.filter((v) => array2.includes(v));
const diff = <T>(array1: T[], array2: T[]) =>
array1.filter((v) => !array2.includes(v));
const symDiff = <T>(array1: T[], array2: T[]) =>
diff(array1, array2).concat(diff(array2, array1));
const union = <T>(array1: T[], array2: T[]) =>
diff(array1, array2).concat(array2);
const intersectionBy = <T>(
array1: T[],
array2: T[],
predicate: (array1Value: T, array2Value: T) => boolean
) => array1.filter((v) => array2.some((u) => predicate(v, u)));
const diffBy = <T>(
array1: T[],
array2: T[],
predicate: (array1Value: T, array2Value: T) => boolean
) => array1.filter((v) => !array2.some((u) => predicate(v, u)));
const uniqueBy = <T>(
array: T[],
predicate: (v: T, i: number, a: T[]) => string
) =>
Object.values(
array.reduce((acc, value, index) => {
acc[predicate(value, index, array)] = value;
return acc;
}, {} as { [key: string]: T })
);
Run Code Online (Sandbox Code Playgroud)
Sam*_*ijo 37
在这种情况下,您可以使用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}
Run Code Online (Sandbox Code Playgroud)
pdb*_*ito 31
function diff(a1, a2) {
return a1.concat(a2).filter(function(val, index, arr){
return arr.indexOf(val) === arr.lastIndexOf(val);
});
}
Run Code Online (Sandbox Code Playgroud)
合并两个数组,唯一值只出现一次,因此indexOf()将与lastIndexOf()相同.
Al_*_*___ 18
要从另一个数组中减去一个数组,只需使用下面的代码段:
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;
});
Run Code Online (Sandbox Code Playgroud)
它将返回['1,'2','6'],它们是第一个数组中第二个不存在的项.
因此,根据您的问题示例,以下代码是确切的解决方案:
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;
});
Run Code Online (Sandbox Code Playgroud)
mae*_*ics 12
使用的解决方案indexOf()适用于小型阵列,但随着它们的长度增长,算法的性能接近O(n^2).这是一个解决方案,通过使用对象作为关联数组将数组条目存储为键,可以更好地处理非常大的数组; 它还自动消除重复条目,但仅适用于字符串值(或可以安全存储为字符串的值):
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']
Run Code Online (Sandbox Code Playgroud)
Sal*_*ali 12
随着ES6与套装和splat操作员的到来(在仅在Firefox中工作,检查兼容性表),您可以编写以下一个班轮:
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)))];
Run Code Online (Sandbox Code Playgroud)
这将导致[ "c", "d" ].
小智 11
计算difference两个阵列之间的Set操作之一.该术语已经表明Set应该使用本机类型,以便提高查找速度.无论如何,当你计算两组之间的差异时,有三种排列:
[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]
Run Code Online (Sandbox Code Playgroud)
这是一个反映这些排列的功能性解决方案.
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) );Run Code Online (Sandbox Code Playgroud)
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) );Run Code Online (Sandbox Code Playgroud)
我想这个例子是一个很好的起点,可以获得函数式编程意味着什么:
使用可以以多种不同方式插入的构建块进行编程.
小智 10
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);
Run Code Online (Sandbox Code Playgroud)
这应输出: [ 1, 2, 6, 7 ]
另一种解决问题的方法
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]
Run Code Online (Sandbox Code Playgroud)
如果你有两个对象列表
const people = [{name: 'cesar', age: 23}]
const morePeople = [{name: 'cesar', age: 23}, {name: 'kevin', age: 26}, {name: 'pedro', age: 25}]
let result2 = morePeople.filter(person => people.every(person2 => !person2.name.includes(person.name)))
Run Code Online (Sandbox Code Playgroud)
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]
Run Code Online (Sandbox Code Playgroud)
这个怎么样:
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));
Run Code Online (Sandbox Code Playgroud)
所以这样你就可以做到array1.diff(array2)与众不同(虽然算法的时间复杂度很高 - 我相信O(array1.length x array2.length))
小智 6
function diffArray(arr1, arr2) {
var newArr = arr1.concat(arr2);
return newArr.filter(function(i){
return newArr.indexOf(i) == newArr.lastIndexOf(i);
});
}
Run Code Online (Sandbox Code Playgroud)
这对我有用
小智 6
使用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);Run Code Online (Sandbox Code Playgroud)
小智 6
const a1 = ['a', 'b', 'c', 'd'];
const a2 = ['a', 'b'];
const diffArr = a1.filter(o => !a2.includes(o));
console.log(diffArr);
Run Code Online (Sandbox Code Playgroud)
输出:
[ 'c', 'd' ]
Run Code Online (Sandbox Code Playgroud)
要查找两个不重复的数组的差异:
function difference(arr1, arr2){
let setA = new Set(arr1);
let differenceSet = new Set(arr2.filter(ele => !setA.has(ele)));
return [...differenceSet ];
}
Run Code Online (Sandbox Code Playgroud)
1.difference([2,2,3,4],[2,3,3,4])会回来[]
2.difference([1,2,3],[4,5,6])会回来[4,5,6]
3.difference([1,2,3,4],[1,2])会回来[]
4.difference([1,2],[1,2,3,4])会回来[3,4]
注意:上述解决方案要求您始终发送较大的数组作为第二个参数。要找到绝对差异,您需要首先找到两者中较大的数组,然后对它们进行处理。
要查找两个不重复的数组的绝对差:
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 ];
}
Run Code Online (Sandbox Code Playgroud)
1.absDifference([2,2,3,4],[2,3,3,4])会回来[]
2.absDifference([1,2,3],[4,5,6])会回来[4,5,6]
3.absDifference([1,2,3,4],[1,2])会回来[3,4]
4.absDifference([1,2],[1,2,3,4])会回来[3,4]
注意两个解决方案中的示例 3
这是另一个可以返回差异的解决方案,就像 git diff 一样:(它是用 typescript 编写的,如果您没有使用 typescript 版本,只需删除类型即可)
/**
* util function to calculate the difference between two arrays (pay attention to 'from' and 'to'),
* it would return the mutations from 'from' to 'to'
* @param { T[] } from
* @param { T[] } to
* @returns { { [x in string]: boolean } } it would return the stringified version of array element, true means added,
* false means removed
*/
export function arrDiff<T>(from: T[], to: T[]): { [x in string]: boolean } {
var diff: { [x in string]: boolean } = {};
var newItems: T[] = []
diff = from.reduce((a, e) => ({ ...a, [JSON.stringify(e)]: true }), {})
for (var i = 0; i < to.length; i++) {
if (diff[JSON.stringify(to[i])]) {
delete diff[JSON.stringify(to[i])]
} else {
newItems.push(to[i])
}
}
return {
...Object.keys(diff).reduce((a, e) => ({ ...a, [e]: false }), {}),
...newItems.reduce((a, e) => ({ ...a, [JSON.stringify(e)]: true }), {})
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个用法示例:
arrDiff(['a', 'b', 'c'], ['a', 'd', 'c', 'f']) //{"b": false, "d": true, "f": true}
Run Code Online (Sandbox Code Playgroud)