使用Underscore.JS合并两个集合

时间:2012-11-22 13:49:02

标签: javascript underscore.js

如果我有两个集合:

c1 - [{a:1},{a:2},{a:3}]

c2 - [{a:1},{a:7},{a:8}]

使用c2c1中的唯一项添加到Underscore.JS的最快方法是什么?集合中的实数为2K c1500 c2,操作经常执行,因此必须具有高效性!

更新1 - 我只使用Underscore.JS几天,我找不到将一个集合添加到另一个集合的方法(我可以过滤c2我自己) - 在Underscore.JS中是微不足道的吗?

4 个答案:

答案 0 :(得分:50)

以下将:

  • 创建一个包含c1和c2所有元素的新数组。见union
  • 从该混合中创建一个仅包含唯一元素的新数组。见uniq

请注意,仅当所有对象都具有属性a时才会起作用。

_.uniq(_.union(c1, c2), false, function(item, key, a){ return item.a; });

您可以在this question中找到其他选项。

答案 1 :(得分:13)

尝试:

_.uniq(_.union(c1, c2), false, _.property('a'))

详细说明:

  1. _.union(*arrays)

      

    计算传入数组的并集。

  2. _.property(key) (自版本1.6.0起)

      

    返回一个函数,该函数本身将返回任何传入对象的key属性。

  3. _.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] );
        }
    }
}

这里是a JSfiddle to test it