var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
任何建议都非常感谢 .
30 回答
11
纯JavaScript解决方案(无库)
与旧版浏览器兼容(不使用 filter )
O(n ^ 2)
可选 fn 回调参数,用于指定如何比较数组项
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(', ')
);
33
要从另一个数组中减去一个数组,只需使用下面的代码段:
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;
});
它将返回['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;
});
17
到目前为止,这是使用jQuery获得您正在寻找的结果的最简单方法:
var diff = $(old_array).not(new_array).get();
diff 现在包含 old_array 中不在 new_array 中的内容
10
这是有效的:基本上合并两个数组,寻找重复项并将未重复的内容推送到新数组中,这是不同的 .
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;
}
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)我相信)
579
function diffArray(arr1, arr2) {
var newArr = arr1.concat(arr2);
return newArr.filter(function(i){
return newArr.indexOf(i) == newArr.lastIndexOf(i);
});
}
这对我有用
294
普通JavaScript
“差异”有两种可能的解释 . 我会让你选择你想要的那个 . 说你有:
var a1 = ['a', 'b' ];
var a2 = [ 'b', 'c'];
如果您想获得 ['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;
}
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;
}
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};
}
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}]
160
我假设你正在比较一个普通的数组 . 如果没有,则需要将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"));
if (!Array.prototype.diff) {
Array.prototype.diff = function (array) {
// if the other array is a falsy value, return a copy of this array
if ((!array) || (!Array.prototype.isPrototypeOf(array))) {
return this.slice(0);
}
var diff = [];
var original = this.slice(0);
for(var i=0; i < array.length; ++i) {
var index = original.indexOf(array[i]);
if (index > -1) {
original.splice(index, 1);
} else {
diff.push(array[i]);
}
}
for (var i=0; i < original.length; ++i) {
diff.push(original[i]);
}
return diff;
}
}
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}
9
littlebit修复了最佳答案
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;
}
这将考虑当前类型的元素 . b / c当我们创建[a1 [i]]时,它会根据其oroginal值将值转换为字符串,因此我们失去了实际值 .
30 回答
纯JavaScript解决方案(无库)
与旧版浏览器兼容(不使用
filter
)O(n ^ 2)
可选
fn
回调参数,用于指定如何比较数组项要从另一个数组中减去一个数组,只需使用下面的代码段:
它将返回['1,'2','6'],它们是第一个数组中第二个不存在的项 .
因此,根据您的问题示例,以下代码是确切的解决方案:
到目前为止,这是使用jQuery获得您正在寻找的结果的最简单方法:
diff
现在包含old_array
中不在new_array
中的内容这是有效的:基本上合并两个数组,寻找重复项并将未重复的内容推送到新数组中,这是不同的 .
如果数组不是简单类型,则可以调整上述答案之一:
此方法适用于复杂对象的数组 .
这个怎么样:
所以这样你可以做
array1.diff(array2)
来获得他们的差异(算法的可怕时间复杂度 - O(array1.length x array2.length)我相信)这对我有用
普通JavaScript
“差异”有两种可能的解释 . 我会让你选择你想要的那个 . 说你有:
['a']
,请使用此功能:['a', 'c']
(a1
或a2
中包含的所有元素,但不是两者都包含 - 所谓的对称差异),请使用此函数:Lodash / Underscore
如果您使用的是lodash,则可以使用_.difference(a1, a2)(上面的情况1)或_.xor(a1, a2)(情况2) .
如果您使用的是Underscore.js,则可以将_.difference(a1, a2)函数用于案例1 .
ES6设置,适用于非常大的阵列
上面的代码适用于所有浏览器 . 但是,对于大于10,000个项目的大型数组,它变得非常慢,因为它具有O(n²)复杂度 . 在许多现代浏览器中,我们可以利用ES6 Set对象来加快速度 . 当Lodash可用时,它会自动使用
Set
. 如果您没有使用lodash,请使用以下实现,灵感来自Axel Rauschmayer's blog post:注意事项
如果您关心-0, +0, NaN或稀疏数组,所有示例的行为可能会令人惊讶或不明显 . (对于大多数用途,这没关系 . )
Joshaven Potter的上述答案很棒 . 但它返回数组B中不在数组C中的元素,但不是相反的方式 . 例如,如果
var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
那么它将输出:==>[1,2,6]
,但 not[1,2,6,7]
,这是两者之间的实际差异 . 您仍然可以使用上面的Potter代码,但只需向后重做一次比较:这应输出:
[ 1, 2, 6, 7 ]
The difference method in Underscore(或其替代品,Lo-Dash)也可以这样做:
与任何Underscore函数一样,您也可以使用更面向对象的样式:
使用ES2015的功能方法
计算两个数组之间的
difference
是Set
操作之一 . 该术语已指示应使用本机Set
类型,以便提高查找速度 . 无论如何,当你计算两组之间的差异时,有三种排列:这是一个反映这些排列的功能性解决方案 .
左差:
正确的区别:
differencer
是微不足道的 . 它只是differencel
与翻转参数 . 您可以为方便起见编写函数:const differencer = flip(differencel)
. 就这样!对称差异:
现在我们有了左边和右边的一个,实现对称的_456036也变得微不足道了:
我想这个例子是一个很好的起点,可以获得函数式编程意味着什么:
Programming with building blocks that can be plugged together in many different ways.
合并两个数组,唯一值只出现一次,因此indexOf()将与lastIndexOf()相同 .
我想要一个类似的函数,它接受了一个旧数组和一个新数组,并给了我一组添加的项目和一系列已删除的项目,我希望它有效(所以没有.contains!) .
您可以在此处使用我提出的解决方案:http://jsbin.com/osewu3/12 .
任何人都可以看到该算法有任何问题/改进吗?谢谢!
代码清单:
响应想要从另一个数据中减去一个数组的人...
如果不超过1000个元素试试这个......
设置一个新变量来复制Array01并将其命名为Array03 .
现在,使用冒泡排序算法将Array01的元素与Array02进行比较,每当找到匹配项时,请执行以下操作Array03 ...
注意:我们正在修改Array03而不是Array01,以免搞砸了冒泡排序的嵌套循环!
最后,通过简单的赋值将Array03的内容复制到Array01,您就完成了 .
我正在寻找一个简单的答案,不涉及使用不同的库,我想出了我自己,我认为这里没有提到 . 我不知道它有多高效或除了它有效之外的任何东西;
对于我的代码我也需要重复,但我想这并不总是首选 .
我想主要的缺点是它可能会比较许多已被拒绝的选项 .
要获得 symmetric difference ,您需要以两种方式比较数组(或者在多个数组的情况下以所有方式)
ES7(ECMAScript 2016)
ES6(ECMAScript 2015)
ES5(ECMAScript 5.1)
Example:
对象数组之间的差异
Example:
我假设你正在比较一个普通的数组 . 如果没有,则需要将for循环更改为for .. in循环 .
如果您不关心向后兼容性,更好的解决方案是使用过滤器 . 但是,这个解决方案仍然有效 .
使用http://phrogz.net/JS/ArraySetMath.js您可以:
使用ES7有更好的方法:
Intersection
对于
[1,2,3] [2,3]
,它将产生[2,3]
. 另一方面,对于[1,2,3] [2,3,5]
将返回相同的内容 .Difference
对于
[1,2,3] [2,3]
,它将产生[1]
. 另一方面,对于[1,2,3] [2,3,5]
将返回相同的东西 .对于 symmetric difference ,您可以这样做:
这样,您将获得一个包含arr1的所有元素的数组,这些元素不在arr2中,反之亦然
正如@Joshaven Potter在他的回答中指出的那样,你可以将它添加到Array.prototype中,这样它就可以这样使用:
使用JavaScript过滤功能的非常简单的解决方案:
另一种解决问题的方法
这是受到Thinker接受的答案的启发,但Thinker的答案似乎假设数组是集合 . 如果数组是
[ "1", "2" ]
和[ "1", "1", "2", "2" ]
,它就会崩溃这些数组之间的区别是
[ "1", "2" ]
. 以下解决方案是O(n * n),因此并不理想,但如果您有大型阵列,它也具有优于Thinker解决方案的内存优势 .如果您首先处理套装,那么Thinker的解决方案肯定会更好 . 如果您有更新版本的Javascript可以访问过滤器,那么您也应该使用它们 . 这仅适用于那些没有处理集合并使用旧版JavaScript(无论出于何种原因)的人......
在这种情况下,您可以使用Set . 它针对这种操作(联合,交叉,差异)进行了优化 .
一旦不允许重复,请确保它适用于您的情况 .
littlebit修复了最佳答案
这将考虑当前类型的元素 . b / c当我们创建[a1 [i]]时,它会根据其oroginal值将值转换为字符串,因此我们失去了实际值 .
随着ES6与套装和splat操作员的到来(仅在Firefox中工作时,请检查compatibility table),您可以编写以下一个班轮:
这将导致
[ "c", "d" ]
.Note indexOf和过滤器在ie9之前不可用 .
只是想......为了挑战;-)这会工作......(对于字符串,数字等基本数组)没有嵌套数组
请注意,排序可能不会如上所述...但如果需要,请调用数组上的.sort()进行排序 .
使用
indexOf()
的解决方案适用于小型阵列,但随着它们的长度增长,算法的性能接近O(n^2)
. 这是一个解决方案,通过使用对象作为关联数组将数组条目存储为键,可以更好地处理非常大的数组;它还自动消除重复条目,但仅适用于字符串值(或可以安全存储为字符串的值):