在对象数组上使用下划线的"差异"方法

Nas*_*Nas 39 javascript underscore.js

_.difference([], [])
Run Code Online (Sandbox Code Playgroud)

当我有原始类型数据时,这种方法工作正常

var a = [1,2,3,4];
var b = [2,5,6];
Run Code Online (Sandbox Code Playgroud)

并且_.difference(a,b)呼叫返回[1,3,4]

但万一我正在使用像

var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];
Run Code Online (Sandbox Code Playgroud)

似乎不起作用

小智 55

尝试使用大小来查找对象数组的差异:

var test = [{a: 1},{b: 2}];
var test2 = [{a: 1}];

_.filter(test, function(obj){ return !_.findWhere(test2, obj); });
Run Code Online (Sandbox Code Playgroud)


Cla*_*ick 30

虽然接受的答案是正确的,而其他答案也提供了好的想法,但还有一个额外的选项,使用下划线很容易实现.

此解决方案依赖于每个具有唯一ID的对象,但在许多情况下这将是正确的,并且您可以在两行代码中获得两个对象数组的差异.

使用下划线的"pluck"方法,您可以快速构建源集和目标集中所有ID的数组.从那里,所有下划线的数组方法将工作,差异,联合,交集等...

在操作之后,从源列表中获取所需的对象列表是微不足道的.这是一个例子:

详细:

var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];

var arr1 = _.pluck(a, "id");
var arr2 = _.pluck(b, "id");
var diff = _.difference(arr1, arr2);
var result = _.filter(a, function(obj) { return diff.indexOf(obj.id) >= 0; });
Run Code Online (Sandbox Code Playgroud)

或者,更简洁地说:

var diff = _.difference(_.pluck(a, "id"), _.pluck(b, "id"));
var result = _.filter(a, function(obj) { return diff.indexOf(obj.id) >= 0; });
Run Code Online (Sandbox Code Playgroud)

当然,可以扩展这种相同的技术以用于任何阵列方法.

  • 很好的答案,我喜欢kontr0l,但Angular喜欢向对象添加一个hashkey属性,所以如果你要比较的东西还没有hashkey,那么比较整个对象会很有挑战性.有了你的答案,我可以单独比较ID,它完美无缺. (5认同)
  • 为了澄清起见,@ maliness在** lodash **中不存在,但是在下划线中仍然存在,这就是问题所在。 (2认同)

Anu*_*yal 15

原因很简单,具有相同内容的对象不是相同的对象,例如

var a = [{'id':1, 'value':10}, {'id':2, 'value':20}]; 
a.indexOf({'id':1, 'value':10})
Run Code Online (Sandbox Code Playgroud)

它不会返回0而是-1,因为我们正在搜索不同的对象

查看源代码http://underscorejs.org/underscore.js,_.difference使用_.contains

_.difference = function(array) {
  var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
  return _.filter(array, function(value){ return !_.contains(rest, value); });
};
Run Code Online (Sandbox Code Playgroud)

并且_.contains 最终使用indexOf因此不会找到对象,除非它们指向同一个对象.

您可以_.contains通过循环遍历所有项目并调用比较回调来改进下划线,您应该能够传递给差异或包含函数,或者您可以检查此版本改进包含方法