31

假设我有两个集合:

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

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

将独特物品添加c2c1使用中的最快方法是什么Underscore.JS?集合中的实数是2Kforc1500for c2,该操作经常执行,所以必须是高性能的!

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

4

4 回答 4

53

以下将:

  • 创建一个包含 c1 和 c2 的所有元素的新数组。见联合
  • 从该组合中,创建一个仅包含唯一元素的新数组。请参阅uniq

请注意,这仅在您的所有对象都具有属性时才有效a

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

您可以在此问题中找到其他选项。

于 2012-11-22T14:38:01.543 回答
16

尝试:

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

详细地:

  1. _.union(*arrays)

    计算传入数组的并集。

  2. _.property(key) (从 1.6.0 版开始)

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

  3. _.uniq(array, [isSorted], [iteratee])

    生成数组的无重复版本,===用于测试对象是否相等。如果您事先知道数组已排序,则传递trueisSorted 将运行更快的算法。如果要基于转换计算唯一项,请传递 iteratee 函数。

于 2015-01-21T11:22:33.637 回答
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};});

上面的like首先将对象列表转换为简单数组(pluck()),然后将它们组合使用union()并最终用于map()创建对象列表。

参考:uniq()

于 2012-11-26T18:17:15.430 回答
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] );
        }
    }
}

这是一个 JSfiddle 来测试它

于 2012-11-22T13:56:56.513 回答