Underscore: _.union 不适用于对象数组

创建于 2015-10-02  ·  32评论  ·  资料来源: jashkenas/underscore

_.union 在传递对象数组时总是会产生重复项。

例如_.union( [ { a:1 } ], [ { a:1 } ])将返回[ { a:1 }, { a:1 } ]

反常的是,underscore 自己的 isEqual 函数会告诉您所讨论的对象是相等的。 也许我们可以有一个标志/选项来指示要使用的相等比较,或者传入比较器的选项?

change

最有用的评论

这个线程启发我添加_.intersectionWith_.differenceWith_.unionWith_.uniqWith来处理我自己的代码中的比较定制。

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

所有32条评论

我很惊讶它还没有接受比较功能。 :+1:

值得指出的是,这适用于所有其他数组计算函数,如差异、交集、唯一性等。

如果可以更新全套数组函数以允许对对象使用不同的相等比较器,那就太好了。

如果我们有一个选项可以根据可以传递给 _.union() 函数的布尔参数值来比较相等性,会不会更容易? 如果它是真的,那么它会自动比较该数组中的所有对象。

例如_.union([1, 2, 3, 10, [{a:1}, {a:1}]], true) ,会输出[1,2,3,10, {a:1}]

@amiral84不,那是无关的。 如果您想要这种行为,请将 union 与 flatten 组合在一起。

@michaelficarra那我是不是错过了这个话题的重点? :D

@amiral84看起来是这样。 功能请求在第一条评论中得到了完整而简洁的解释。

潜在的问题似乎在_.uniq因为_.union只是一个用于 unique 和 flatten 的包装函数。

_.union = restArgs(function(arrays) {
  return _.uniq(flatten(arrays, true, true));
});

这个线程启发我添加_.intersectionWith_.differenceWith_.unionWith_.uniqWith来处理我自己的代码中的比较定制。

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

或者类似_.isCollection来确定你是否正在处理一个集合。 如果处理一个集合,那么比较应该使用_.isEqual而不是=== ,这在集合的情况下没有好处。

@dperrymorrow

应该使用_.isEqual而不是=== ,这在集合的情况下没有好处。

动态切换听起来是个坏主意。 JS 在很多事情上使用===SameValueZero比较。 如果需要超出这些比较范围,则可以使用_.uniqWith方法。

感谢这个@jdalton ,你提到的 _opWith 函数对于我想要实现的目标来说绝对是完美的。 知道它们什么时候可以通过发布获得吗?

@jdalton比较的好点,但是您通常不会在集合中使用唯一键而不是强制 Underscore 检测对象之间的整个差异吗?

以下不会解决@wilhen01的请求_(尽管比期望的更冗长)_

_.chain([{ a: 1 }]).union( [{a: 1}]).unique('a').value();
//=> [{a: 1}]

以下不会解决@wilhen01的请求(尽管比期望的更冗长)

_.uniq已经支持。

对,这就是我的观点,上面的代码目前按发布的方式工作。
你不能用联合结果的键来调用 uniq / unique 吗?

@dperrymorrow在该示例之外并添加另一个属性

好的,明白了,抱歉……我不想好战,只是想完全理解这个问题。 我喜欢在_.uniqWith函数上提交拉取请求。

不用担心,那会很糟糕。

_.intersectionWith、_.differenceWith、_.unionWith 和 _.uniqWith

只允许将比较函数作为最终参数选择性地传递,而不是创建四个新函数,这不是更好的 API 吗?

@jashkenas

只允许将比较函数作为最终参数选择性地传递,而不是创建四个新函数,这不是更好的 API 吗?

是的,它可以做到,但有一些复杂性,因为像_.uniq已经支持传递迭代对象,并且由于对二进制/排序搜索标志和上下文参数的支持

是的,一个完全不幸的设计问题。 但是仅仅为了允许比较器而创建新函数也不是正确的解决方案。

好的,那么额外的比较函数参数是去这里的方法吗?
如果是这样,我可以更新我的拉取请求。

我预见到的唯一棘手的部分是使参数解析像上面提到的有点麻烦

_.uniq = _.unique = function(array, isSorted, iteratee, context) {
  if (!_.isBoolean(isSorted)) {
    context = iteratee;
    iteratee = isSorted;
    isSorted = false;
  }
//...

也许添加额外的检查以查看是否 isSorted _.isFunction然后将其视为比较器。

@jashkenas

但是仅仅为了允许比较器而创建新函数也不是正确的解决方案。

对于糟糕的情况,这可能是最好的选择。 我最近开始尝试拆分重载的功能,并且对结果非常满意。 虽然它增加了 API 表面,但它允许更简单的实现和类似主题的方法分组,如maxByuniqBypickByuniqWithunionWithzipWithsortedIndexBysortedIndexOfsortedUniq 。 在uniq的情况下,虽然我目前仍然使用共享基函数。

已更新此拉取请求 #2368 谢谢。

我 :+1: 对于uniqByuniqWith 。 我将完全反对进一步超载uniq (如目前提议的 #2368)

:+1: @megawac , uniqBy

Fwiw lodash 将使用uniqBy作为_.uniq(array, iteratee)的拆分形式和_.uniqWith作为允许比较器自定义的形式。

是的,第二个想法uniqWith是一个更好的名字

那么我应该使用单独的方法在 Lodash 上拉取请求吗?
我以为这两个项目合并了,我错了吗?

@dperrymorrow

我应该使用单独的方法在 Lodash 上拉取请求吗

不需要,它们已经在 lodash 的边缘主分支中。

我以为这两个项目合并了,我错了吗?

还没有。 不过,Lodash v4 证明了合并的一些想法。

@jdalton你能否详细说明一下_.uniqWith与其他迭代器的实现。

@帕夫尼
当然。 你可以查看lodash/npm/_baseUniq
如果comparator被传递,它使用arrayIncludesWith助手来做检查而不是arrayIncludes (Underscore 的contains )。

@jdalton这对我有帮助。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

afranioce picture afranioce  ·  8评论

acl0056 picture acl0056  ·  5评论

jezen picture jezen  ·  8评论

ksullivan picture ksullivan  ·  9评论

danilopolani picture danilopolani  ·  5评论