如果我有两个集合:
c1 - [{a:1},{a:2},{a:3}]
和
c2 - [{a:1},{a:7},{a:8}]
使用c2
将c1
中的唯一项添加到Underscore.JS
的最快方法是什么?集合中的实数为2K
c1
和500
c2
,操作经常执行,因此必须具有高效性!
更新1 - 我只使用Underscore.JS
几天,我找不到将一个集合添加到另一个集合的方法(我可以过滤c2
我自己) - 在Underscore.JS
中是微不足道的吗?
答案 0 :(得分:50)
以下将:
请注意,仅当所有对象都具有属性a
时才会起作用。
_.uniq(_.union(c1, c2), false, function(item, key, a){ return item.a; });
您可以在this question中找到其他选项。
答案 1 :(得分:13)
尝试:
_.uniq(_.union(c1, c2), false, _.property('a'))
详细说明:
_.union(*arrays)
计算传入数组的并集。
_.property(key)
(自版本1.6.0起)
返回一个函数,该函数本身将返回任何传入对象的key属性。
_.uniq(array, [isSorted], [iteratee])
使用
===
生成数组的无副本版本以测试对象相等性。如果您事先知道数组已排序,则传递true
for isSorted将运行更快的算法。如果要根据转换计算唯一项,请传递iteratee函数。
答案 2 :(得分:6)
uniq()
函数的文档提到如果列表已排序,它运行得更快。同样使用链式调用可以提高可读性。所以你可以这样做:
_.chain(c1).union(c2).sortBy("a").uniq(true, function(item){ return item.a; }).value();
或者如果您更喜欢未链接的版本(缩短了11个字符但可读性较差):
_.uniq(_.sortBy(_.union(c1,c2),"a"),true, function(item){ return item.a; });
uniq()
的文档和示例没有说清楚回调函数的工作原理。 uniq()
函数的算法在两个列表的每个元素上调用此函数。如果此函数的结果相同,则删除该元素(假设它是重复的)。
union()
可以在数组上调用时防止重复。我们也可以使用这个事实:
_.map(_.union(_.pluck(c1,"a"),_.pluck(c2,"a")),function (item) {return {a:item};});
上面首先将对象列表转换为简单数组(pluck()
),然后使用union()
将它们组合起来,最后使用map()
制作对象列表。
参考:uniq()
答案 3 :(得分:1)
由于两个对象中都有大量属性,并且这种算法经常运行,因此最好使用核心Javascript而不是任何库:
//adds all new properties from the src to dst. If the property already exists, updates the number in dst. dst and src are objects
function extendNumberSet( dst, src ) {
var allVals = [];
for ( var i = 0; i < dst.length; i++ ) {
allVals.push(dst[i].a);
}
for ( var i = 0; i < src.length; i++ ) {
if ( allVals.indexOf( src[i].a ) === -1 ) {
dst.push( src[i] );
}
}
}