获得两个对象数组之间差异的有效方法?

时间:2011-07-16 05:53:05

标签: javascript arrays diff

我有两个对象数组:

var a = [  {'id': 20},   {'id': 15},   {'id': 10},   {'id': 17},   {'id': 23}  ];

var b = [ {'id': 90},   {'id': 15},    {'id': 17},   {'id': 23}  ];  

我想要获取a中的对象,但不是b中的对象。此示例的结果将是:

{'id': 20}{'id': 10}

因为数组可能很大,所以我需要一种有效的方法来实现这一点。

4 个答案:

答案 0 :(得分:20)

// Make hashtable of ids in B
var bIds = {}
b.forEach(function(obj){
    bIds[obj.id] = obj;
});

// Return all elements in A, unless in B
return a.filter(function(obj){
    return !(obj.id in bIds);
});

非常小的附录:如果列表非常大并且您希望避免2个额外内存的因素,您可以首先将对象存储在散列图中而不是使用列表,假设ID是唯一的:a = {20:{etc:...}, 15:{etc:...}, 10:{etc:...}, 17:{etc:...}, 23:{etc:...}}。我个人会这样做。或者:其次,javascript就地排序列表,因此它不会使用更多内存。例如a.sort((x,y)=>x.id-y.id)排序会比上面更差,因为它是O(N log(N))。但是如果你不得不对它进行排序,那么有一个O(N)算法涉及两个排序列表:即,你将两个列表一起考虑,并重复从列表中取最左边(最小)的元素(即检查,然后增加你所采用的列表中的指针/书签)。这就像合并排序一样,但是要更加小心地找到相同的项目...而且可能会讨厌代码。第三,如果列表是遗留代码,并且您希望将其转换为没有内存开销的散列映射,则还可以通过重复弹出列表中的元素并将其转换为散列图来逐个元素地执行此操作。

答案 1 :(得分:5)

使用lodash 4.12.0,您可以使用_.differenceBy

_.differenceBy(a, b, 'id');

答案 2 :(得分:2)

执行此操作的一般方法是:

  1. 将b中的所有对象放入哈希表
  2. 迭代a,为每个项目检查它是否在哈希表中
  3. 现在很多编程环境都设置了和/或HashSet实现,这使得它非常简单。

    在特殊情况下,其他方式可能更有效。例如,如果你的元素是字节大小的值,并且a和b都相当大,那么我将使用256个元素的布尔数组“flags”,将all初始化为false。然后,对于b的每个元素x,将flags [x]设置为true。然后迭代a,对于a中的每个y,检查是否设置了flags [y]。

答案 3 :(得分:0)

如果你不喜欢包含库使用underscore.js它有一个很好的交集功能 http://documentcloud.github.com/underscore/