如何使用lodash或underscore从两个数组中删除相同的对象?

8
现在我有两个对象数组,
var arr1 = [{id: 0, name: 'Jack'}, {id: 1, name: 'Ben'}, {id: 2, name: 'Leon'}, {id: 3, name: 'Gavin'}];
var arr2 =  [{id: 0, name: 'Jack'}, {id: 5, name: 'Jet'}, {id: 2, name: 'Leon'}];

我希望删除在arr1arr2中相同id的对象,所以结果如下:

var arr1 = [{id: 1, name: 'Ben'}, {id: 3, name: 'Gavin'}];
var arr2 =  [{id: 5, name: 'Jet'}];

如何使用 lodashunderscore 实现呢?

以下是我实现的方法。

arr1_ids = _.pluck(arr1, 'id');
arr2_ids = _.pluck(arr2, 'id');

same_ids = _.intersection(arr1_ids, arr2_ids);

arr1 = _.remove(arr1, function(e) { return !_.contains(same_ids, e.id); });
arr2 = _.remove(arr2, function(e) { return !_.contains(same_ids, e.id); });

有没有更好的方法来做这件事?

这个可以用 .uniq 完成吗? - Dom
如何使用 uniq 实现这个功能? - zangw
定义“更好”。是指更快?更少的代码?更易于维护?;-) - RobG
3个回答

11

你能使用 _.difference 吗?

same_elements = _.intersection(arr1, arr2);
arr1 = _.difference(arr1, same_elements);
arr2 = _.difference(arr2, same_elements);

1
我认为.intersection()不会正确比较内部对象。 - Ja͢ck
1
@Ja͢ck 然后使用_.intersectionBy()_.intersectionWith() - trusktr
1
_.intersectionBy(arr1, arr2, 'id') 绝对可行 - 我刚用它完成了同样的操作。 - derivative

3
我不确定如何使用underscore或lodash完成此操作,但这里是JavaScript的实现。
它创建了一个过滤函数,然后您可以将其应用于两个数组,以仅保留不属于交集的元素。

var arr1 = [{id: 0, name: 'Jack'}, {id: 1, name: 'Ben'}, {id: 2, name: 'Leon'}, {id: 3, name: 'Gavin'}];
var arr2 =  [{id: 0, name: 'Jack'}, {id: 5, name: 'Jet'}, {id: 2, name: 'Leon'}];

var negative_intersection_filter = function(a, b) {
  // create a map to speed up the filtering later
  var map = a.reduce(function(map, current) {
    // perform the intersection
    map[current.id] = b.some(function(item) {
      return item.id == current.id;
    });
    return map;
  }, {});

  // our filtering function, simple
  return function(item) {
    return !map[item.id];
  }
}(arr1, arr2);

// apply the filter here
arr1 = arr1.filter(negative_intersection_filter);
arr2 = arr2.filter(negative_intersection_filter);
console.log(arr1);
console.log(arr2);


1

我认为你的算法是正确的,这里提供一种稍微不同的纯js方法。为了简洁起见,我使用了a, b而不是arr1, arr2:

// Collect ids and sort
var ids = a.map(function(obj) {return obj.id}).concat(b.map(function(obj) {return obj.id})).sort();

// Get IDs that aren't duplicates
var nonDups = ids.filter(function(v, i, o){return v !== o[i-1] && v !== o[i+1]});

// Keep only the non-duplicates in each array
a.reduceRight(function(pre, cur, i, o){if (nonDups.indexOf(cur.id) == -1) o.splice(i, 1)},0);
b.reduceRight(function(pre, cur, i, o){if (nonDups.indexOf(cur.id) == -1) o.splice(i, 1)},0);

JSON.stringify(a)  // [{"id":1,"name":"Ben"},{"id":3,"name":"Gavin"}]
JSON.stringify(b)  // [{"id":5,"name":"Jet"}]
< p > < em > reduceRight 仅用于反向迭代每个数组,以便剪切不影响迭代。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接