_.union 在传递对象数组时总是会产生重复项。
例如_.union( [ { a:1 } ], [ { a:1 } ])
将返回[ { a:1 }, { a:1 } ]
反常的是,underscore 自己的 isEqual 函数会告诉您所讨论的对象是相等的。 也许我们可以有一个标志/选项来指示要使用的相等比较,或者传入比较器的选项?
我很惊讶它还没有接受比较功能。 :+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 表面,但它允许更简单的实现和类似主题的方法分组,如maxBy
、 uniqBy
、 pickBy
或uniqWith
、 unionWith
、 zipWith
或sortedIndexBy
、 sortedIndexOf
、 sortedUniq
。 在uniq
的情况下,虽然我目前仍然使用共享基函数。
已更新此拉取请求 #2368 谢谢。
我 :+1: 对于uniqBy
或uniqWith
。 我将完全反对进一步超载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这对我有帮助。
最有用的评论
这个线程启发我添加
_.intersectionWith
、_.differenceWith
、_.unionWith
和_.uniqWith
来处理我自己的代码中的比较定制。