Javascript 数组 - 根据另一个 属性 删除重复项

Javascript Array - Remove duplicates based on another property

根据另一个 属性 的值对复杂数组进行重复数据删除的最有效方法是什么?我发现了很多可以对数组或复杂数组进行重复数据删除的示例,但不是这个特定的用例。

我正在尝试查找第 3 列(州)中具有唯一值且第 2 列(许可证)中编号最大的记录

var arrayWithDuplicates = [
    ["Boat", 1, "NV"],
    ["Car", 7, "CA"],
    ["Boat", 3, "NV"],
    ["Boat", 4, "CA"],
    ["Car", 5, "OR"],
    ["Boat", 6, "CA"],
];

期望的结果

var outputArray = [
    ["Car", 7, "CA"],
    ["Boat", 3, "NV"],
    ["Car", 5, "OR"]
];

这可行,但不确定是否适用于大型数据集

var arrayWithDuplicates = [
  ["Boat", 1, "NV"],
  ["Car", 7, "CA"],
  ["Boat", 3, "NV"],
  ["Boat", 4, "CA"],
  ["Car", 5, "OR"],
  ["Boat", 6, "CA"],
];
let arr= arrayWithDuplicates;
let unique = []
for (let i = 0; i < arr.length; i++) {
  let found = false;
  for (let j = 0; j < unique.length; j++) {
    if (arr[i][2] === unique[j][2]) {
      found = true;
      if (arr[i][1] > unique[j][1]) {
        unique[j] = arr[i];
      }
      break;
    }
  }
  if (!found) {
    unique.push(arr[i])
  }
}
console.log(unique);

[["Boat", 3, "NV"], ["Boat", 7, "CA"], ["Car", 5, "OR"]]

您可以看到建议解决方案的性能:https://jsbench.me/eskxxcwnhn/1

使用排序和归约

const arrayWithDuplicates = [ ["Boat", 1, "NV"], ["Car", 7, "CA"], ["Boat", 3, "NV"], ["Boat", 4, "CA"], ["Car", 5, "OR"], ["Boat", 6, "CA"], ]; 

let deduped = [...arrayWithDuplicates]; // take a copy

deduped.sort((a, b) => { // sorts in place
  if (a[0] < b[0]) return 1; // sort on names
  if (a[0] > b[0]) return -1;
  return b[1] - a[1]; // sort on second element
})

// reduce into an object keyed on state
deduped = Object.values(  // take only the values from the object
  deduped.reduce((acc, cur) => {
    const state = cur[2];
    if (!acc[state]) acc[state] = cur;
    return acc;
},{}))
console.log(deduped)

解决问题的一种方法是使用 Map 实例来保存最相关的值。如果遇到另一个,请更换它。然后,当您完成迭代时,您将获取 Map 实例中存在的值。

const arrayWithDuplicates = [
  ["Boat", 1, "NV"],
  ["Car", 7, "CA"],
  ["Boat", 3, "NV"],
  ["Boat", 4, "CA"],
  ["Car", 5, "OR"],
  ["Boat", 6, "CA"],
];

const lookup = new Map();
for (const record of arrayWithDuplicates) {
  const key = record[2];
  
  if (!lookup.has(key)) {
    lookup.set(key, record);
    continue;
  }
  
  const other = lookup.get(key);
  if (record[1] > other[1]) {
    // Iteration order is based on insertion order. By removing the
    // current value first, the new value will be placed at the end.
    // If you don't care about the order, deletion can be omitted.
    lookup.delete(key);
    lookup.set(key, record);
  }
}

const result = Array.from(lookup.values());
console.log(result);

请注意,以下代码序列可能是一个相当繁重的操作:

lookup.delete(key);
lookup.set(key, record);

由于它重新排列了地图内容的迭代顺序。这只会按照您要查找的顺序得到结果。如果结果项的顺序无关紧要,则应删除 lookup.delete(key) 调用以提高执行速度。

尽管使用 Map 实例可能会对小型集合产生一些执行开销。当集合变大时,改进的查找速度真正闪耀。