【问题标题】:get duplicates in array of objects获取对象数组中的重复项
【发布时间】:2020-05-30 18:35:43
【问题描述】:

我有一组对象。

let coordinates = [
    { x: 8, y: 1 },
    { x: 8, y: 3 },
    { x: 6, y: 5 },
    { x: 4, y: 6 },
    { x: 3, y: 7 },
    { x: 6, y: 5 },
    { x: 3, y: 3 },
    { x: 1, y: 4 },
    { x: 3, y: 3 }
]

我偶然发现了这个blog 和这个stackoverflow question,但它只能让我找到基于一个属性的重复对象,但我想获取基于xy 属性的重复对象,如下所示:

[
    { x: 6, y: 5 },
    { x: 3, y: 3 }
]

【问题讨论】:

  • 预期结果是什么?
  • @brk 这是我问题的最后一部分

标签: javascript


【解决方案1】:

我们应用过滤器来检查索引的唯一性,如果元素是重复的,它将计算初始索引并过滤掉当前索引。

var coordinates = [ { x: 8, y: 1 }, { x: 6, y: 5 }, { x: 4, y: 6 }, { x: 3, y: 7 }, { x: 6, y: 5 }, { x: 3, y: 3 }, { x: 1, y: 4 }, { x: 3, y: 3 }];

var result = coordinates.filter((val, i, self)=>self.findIndex(k=>k.x==val.x && k.y == val.y)!=i);

console.log(result)

更新

coordinates = [ { x: 6, y: 5 }, { x: 6, y: 5 }, { x: 6, y: 5 },{ x: 4, y: 6 }, { x: 3, y: 7 }, { x: 6, y: 5 }, { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 1, y: 4 }, { x: 3, y: 3 },{ x: 6, y: 5 }];

result = coordinates.reduce((acc, elem)=>{
  key = Object.values(elem).join('|');
  acc.unique[key] = acc.unique[key] || [];
  acc.unique[key].length >0 ? acc.duplicate[key] = elem : acc.unique[key].push(elem);
  return acc;
},{unique:{},duplicate:{}});

duplicate = Object.values(result.duplicate);
unique = Object.values(result.unique);

console.log(duplicate);
console.log(unique);

【讨论】:

  • @breekoy 另外,如果您查看filter 函数,它接受各种参数,例如(val, i, self) val 代表当前迭代元素,i 代表index countself 是@ 987654329@.
  • 这是错误的答案。它打破了数组包含超过 2 个 var coordinates = [ { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 3, y: 3 }, ] 的重复项
【解决方案2】:

所有答案并不完全正确,因为它们不适用于具有超过 2 个相同值重复的数组,即:

var coordinates = [
  { x: 8, y: 1 },
  { x: 8, y: 1 },
  { x: 8, y: 1 }
]

我使用JSON.stringify() 和 Set 结构从数组中获取唯一重复项。对于输出,我将字符串解析回对象。

var coordinates = [
      { x: 8, y: 1 },
      { x: 6, y: 5 },
      { x: 4, y: 6 },
      { x: 3, y: 7 },
      { x: 6, y: 5 },
      { x: 3, y: 3 },
      { x: 1, y: 4 },
      { x: 3, y: 3 },
      { x: 3, y: 3 },
]
    
const duplicates = new Set();
const reducer = (set, val, index, arr) => arr.findIndex(k => k.x == val.x && k.y == val.y) != index ? set.add(JSON.stringify(val)) : set
    
coordinates.reduce(reducer, duplicates)
    
console.log(Array.from(duplicates).map(el => JSON.parse(el)))

【讨论】:

    【解决方案3】:

    您可以使用 reduce 和另一个数组。在 reduce 回调中使用 x & y 创建一个对象键并检查该键是否存在于累加器对象中。如果存在,则将 tyhe 值推送到 dupArray

    let coordinates = [
      { x: 8, y: 1 },
      { x: 8, y: 3 },
      { x: 6, y: 5 },
      { x: 4, y: 6 },
      { x: 3, y: 7 },
      { x: 6, y: 5 },
      { x: 3, y: 3 },
      { x: 1, y: 4 },
      { x: 3, y: 3 }
    ];
    let dupArray = [];
    let dups = coordinates.reduce((acc, curr) => {
      const crtKey = '' + curr.x + '' + curr.y;
      if (!acc[crtKey]) {
        acc[crtKey] = 1;
      } else {
        dupArray.push(curr);
      }
      return acc;
    }, {});
    
    console.log(dupArray)

    【讨论】:

    • 我认为+ curr.x之前的第一个''是多余的
    • @zb22 因为我希望键是字符串,否则键将是数字,例如像 9(6+3) 或 9(5+4) 这样的键将是相同的,这将给出错误的结果
    • 是的,但是 curr.x + '' + curr.y 使它成为一个字符串,一旦你把 '' 放在它们之间
    • 这个答案也因超过 2 个重复而中断var coordinates = [ { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 3, y: 3 }, ]
    • 这在我们想要重复的时候很直观,我们不需要重复的重复。只有唯一的重复项。
    【解决方案4】:

    这仅通过迭代所有数组项过滤重复的数组对象,并且对于每个项,再次迭代数组,使用some检查该特定项是否在数组中的任何位置(arr)的位置在当前项之前 (idx1),并将当前项与 some iterator 中的选中项进行比较,方法是将两者都转换为 "string"

    let coordinates = [
        { x: 8, y: 1 },
        { x: 8, y: 3 },
        { x: 6, y: 5 },
        { x: 4, y: 6 },
        { x: 3, y: 7 },
        { x: 6, y: 5 },
        { x: 3, y: 3 },
        { x: 1, y: 4 },
        { x: 3, y: 3 }
    ]
    
    const dups = coordinates.filter(({x, y}, idx1, arr) => 
        arr.some(({x:x2,y:y2}, idx2) => idx2 < idx1 && ""+x+y == ""+x2+y2 ) 
    )
    
    console.log( dups )

    为了使检查更加稳健,通过允许比较任何键,what-so-ever JSON.stringify 可用于比较数组(假设所有数组项都是对象:

    const dups = coordinates.filter((item, idx1, arr) => 
       arr.some((item2, idx2) => idx2 < idx1 && JSON.stringify(item) == JSON.stringify(item2)) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-21
      • 2019-04-12
      • 1970-01-01
      • 2019-06-28
      • 2021-07-20
      • 2018-10-03
      • 2022-01-21
      • 2021-09-14
      相关资源
      最近更新 更多