Javascript 下划线/lodash 由多个属性唯一
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26306415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
underscore/lodash unique by multiple properties
提问by Jeff Storey
I have an array of objects with duplicates and I'm trying to get a unique listing, where uniqueness is defined by a subset of the properties of the object. For example,
我有一组重复的对象,我正在尝试获得一个唯一的列表,其中唯一性由对象属性的子集定义。例如,
{a:"1",b:"1",c:"2"}
And I want to ignore cin the uniqueness comparison.
我想c在唯一性比较中忽略。
I can do something like
我可以做类似的事情
_.uniq(myArray,function(element) { return element.a + "_" + element+b});
I was hoping I could do
我希望我能做到
_.uniq(myArray,function(element) { return {a:element.a, b:element.b} });
But that doesn't work. Is there something like that I can do, or do I need to create a comparable representation of the object if I'm comparing multiple properties?
但这不起作用。是否有类似的事情我可以做,或者如果我比较多个属性,我是否需要创建对象的可比较表示?
回答by voithos
There doesn't seem to be a straightforward way to do this, unfortunately. Short of writing your own function for this, you'll need to return something that can be directly compared for equality (as in your first example).
不幸的是,似乎没有一种直接的方法可以做到这一点。除了为此编写自己的函数之外,您还需要返回可以直接比较相等性的内容(如第一个示例中所示)。
One method would be to just .join()the properties you need:
一种方法是只.join()使用您需要的属性:
_.uniqBy(myArray, function(elem) { return [elem.a, elem.b].join(); });
Alternatively, you can use _.pickor _.omitto remove whatever you don't need. From there, you could use _.valueswith a .join(), or even just JSON.stringify:
或者,您可以使用_.pick或_.omit删除不需要的任何内容。从那里,你可以使用_.valuesa .join(),甚至只是JSON.stringify:
_.uniqBy(myArray, function(elem) {
return JSON.stringify(_.pick(elem, ['a', 'b']));
});
Keep in mind that objects are not deterministic as far as property order goes, so you may want to just stick to the explicit array approach.
请记住,就属性顺序而言,对象不是确定性的,因此您可能只想坚持使用显式数组方法。
P.S. Replace uniqBywith uniqfor Lodash < 4
PS替换uniqBy以uniq用于Lodash <4
回答by Reed Dunkle
Use Lodash's uniqWithmethod:
使用 Lodash 的uniqWith方法:
_.uniqWith(array, [comparator])
_.uniqWith(array, [comparator])
This method is like
_.uniqexcept that it acceptscomparatorwhich is invoked to compare elements ofarray. The order of result values is determined by the order they occur in the array.The comparator is invoked with two arguments: (arrVal, othVal).
这个方法很像,
_.uniq除了它接受comparator哪个被调用来比较 的元素array。结果值的顺序由它们在数组中出现的顺序决定。比较器用两个参数调用:(arrVal, othVal)。
When the comparatorreturns true, the items are considered duplicates and only the first occurrence will be included in the new array.
当comparator返回时true,这些项目被认为是重复的,只有第一次出现的项目才会包含在新数组中。
Example:
I have a list of locations with latitudeand longitude-- some of which are identical -- and I want to see the list of unique locations:
示例:
我有一个带有latitude和的位置列表longitude——其中一些是相同的——我想查看唯一位置的列表:
const locations = [
{
name: "Office 1",
latitude: -30,
longitude: -30
},
{
name: "Office 2",
latitude: -30,
longitude: 10
},
{
name: "Office 3",
latitude: -30,
longitude: 10
}
];
const uniqueLocations = _.uniqWith(
locations,
(locationA, locationB) =>
locationA.latitude === locationB.latitude &&
locationA.longitude === locationB.longitude
);
// Result has Office 1 and Office 2
回答by IndyWill
I do think that the join() approach is still the simplest. Despite concerns raised in the previous solution, I think choosing the right separator is the key to avoiding the identified pitfalls (with different value sets returning the same joined value). Keep in mind, the separator need not be a single character, it can be any string that you are confident will not occur naturally in the data itself. I do this all the time and am fond of using '~!$~' as my separator. It can also include special characters like \t\r\n etc.
我确实认为 join() 方法仍然是最简单的。尽管在之前的解决方案中提出了一些担忧,但我认为选择正确的分隔符是避免识别出的陷阱(不同的值集返回相同的连接值)的关键。请记住,分隔符不必是单个字符,它可以是您确信不会在数据本身中自然出现的任何字符串。我一直这样做并且喜欢使用 '~!$~' 作为我的分隔符。它还可以包含特殊字符,如 \t\r\n 等。
If the data contained is truly that unpredictable, perhaps the max length is known and you could simply pad each element to its max length before joining.
如果包含的数据确实是不可预测的,也许最大长度是已知的,您可以在加入之前简单地将每个元素填充到其最大长度。
回答by Trevor
There is a hint in @voithos and @Danail combined answer. How I solved this was to add a unique key on the objects in my array.
@voithos 和 @Danail 的组合答案中有一个提示。我如何解决这个问题是在我的数组中的对象上添加一个唯一的键。
Starting Sample Data
开始样本数据
const animalArray = [
{ a: 4, b: 'cat', d: 'generic' },
{ a: 5, b: 'cat', d: 'generic' },
{ a: 4, b: 'dog', d: 'generic' },
{ a: 4, b: 'cat', d: 'generic' },
];
In the example above, I want the array to be unique by aand bbut right now I have two objects that have a: 4and b: 'cat'. By combining a + b into a string I can get a unique key to check by.
在上面的示例中,我希望数组是唯一的a,b但是现在我有两个对象具有a: 4和b: 'cat'。通过将 a + b 组合成一个字符串,我可以获得一个唯一的键来检查。
{ a: 4, b: 'cat', d: 'generic', id: `${a}-${b}` }. // id is now '4-cat'
Note:You obviously need to map over the data or do this during creation of the object as you cannot reference properties of an object within the same object.
注意:您显然需要映射数据或在创建对象期间执行此操作,因为您无法在同一对象中引用对象的属性。
Now the comparison is simple...
现在比较很简单......
_.uniqBy(animalArray, 'id');
The resulting array will be length of 3 it will have removed the last duplicate.
结果数组的长度为 3,它将删除最后一个重复项。
回答by Matias
Here there's the correct answer
这里有正确答案
javascript - lodash - create a unique list based on multiple attributes.
javascript-lodash - 创建一个基于多个属性的唯一列表。
FYI var result = _.uniqBy(list, v => [v.id, v.sequence].join());
供参考 var result = _.uniqBy(list, v => [v.id, v.sequence].join());

