下划线/洛达什由多个属性唯一

underscore/lodash unique by multiple properties

本文关键字:属性 唯一 下划线      更新时间:2023-09-26

我有一个重复的对象数组,我正在尝试获取一个唯一的列表,其中唯一性由对象属性的子集定义。例如

{a:"1",b:"1",c:"2"}

我想忽略唯一性比较中的c

我可以做类似的事情

_.uniq(myArray,function(element) { return element.a + "_" + element+b});

我希望我能做到

_.uniq(myArray,function(element) { return {a:element.a, b:element.b} });

但这行不通。我可以做类似的事情吗,或者如果我比较多个属性,我是否需要创建对象的可比较表示形式?

使用 Lodash 的uniqWith方法:

_.uniqWith(array, [comparator])

此方法与_.uniq类似,只是它接受comparator,它被调用以比较array的元素。结果值的顺序由它们在数组中出现的顺序决定。比较器使用两个参数调用:(arrVal,othVal(。

comparator返回true时,这些项目被视为重复项,并且只有第一次出现才会包含在新数组中。

<小时 />

示例:
我有一个带有latitudelongitude坐标的位置列表 - 其中一些是相同的 - 我想查看具有唯一坐标的位置列表:

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

不幸的是,似乎没有一种简单的方法可以做到这一点。如果不为此编写自己的函数,则需要返回可以直接比较相等性的内容(如第一个示例所示(。

一种方法是只.join()您需要的属性:

_.uniqBy(myArray, function(elem) { return [elem.a, elem.b].join(); });

或者,您可以使用_.pick_.omit删除不需要的任何内容。从那里,您可以将_.values.join()一起使用,甚至只是JSON.stringify

_.uniqBy(myArray, function(elem) {
    return JSON.stringify(_.pick(elem, ['a', 'b']));
});

请记住,就属性顺序而言,对象不是确定性的,因此您可能只想坚持使用显式数组方法。

附言将 uniqBy 替换为 uniq 的 Lodash <4

这里有正确的答案

JavaScript - Lodash - 基于多个属性创建一个唯一的列表。

仅供参考var result = _.uniqBy(list, v => [v.id, v.sequence].join());

晚了,但我在 lodash 文档中找到了这个。

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
 
_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]

我确实认为 join(( 方法仍然是最简单的。尽管在前面的解决方案中提出了问题,但我认为选择正确的分隔符是避免已识别陷阱的关键(不同的值集返回相同的连接值(。请记住,分隔符不必是单个字符,它可以是您确信不会在数据本身中自然出现的任何字符串。我一直这样做,并且喜欢使用"~!$~"作为我的分隔符。它还可以包含特殊字符,如 ''t''r' 等。

如果包含的数据确实是不可预测的,也许最大长度是已知的,您可以在连接之前简单地将每个元素填充到其最大长度。

@voithos和@Danail组合答案中有一个提示。我解决这个问题的方式是在数组中的对象上添加一个唯一键。

起始示例数据

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' },
];

在上面的例子中,我希望数组在ab上是唯一的,但现在我有两个对象具有a: 4b: 'cat'。通过将 a + b 组合成一个字符串,我可以得到一个唯一的键来检查。

{ a: 4, b: 'cat', d: 'generic', id: `${a}-${b}` }. // id is now '4-cat'

注: 您显然需要在创建对象期间映射数据或执行此操作,因为您无法在同一对象中引用对象的属性。

现在比较很简单...

_.uniqBy(animalArray, 'id');

生成的数组长度为 3,它将删除最后一个重复项。