从对象数组中的嵌套数组中删除重复项

Posted

技术标签:

【中文标题】从对象数组中的嵌套数组中删除重复项【英文标题】:Remove duplicates from nested array in array of objects 【发布时间】:2021-08-23 16:23:57 【问题描述】:

我有这个对象数组:

const arrayOfObjects = [
    id: 10,
    children: [1000]
  ,
  
    id: 10,
    children: [2000]
  ,
  
    id: 20,
    children: [1000]
  ,
  
    id: 20,
    children: [1000, 2000]
  ,
  
    id: 20,
    children: [2000]
  ,
];

我想使用此代码删除重复项:

  const arrayHashMap = arrayOfObjects.reduce((obj, item) => 
    if (obj[item.id]) 
      // obj[item.id].children.push(...item.children);
      const temporaryArray = [...obj[item.id].children, ...item.children];
      obj[item.id].children = [...new Set(temporaryArray)];
     else 
      obj[item.id] = 
        ...item
      ;
    
    return obj;
  , );
  const result = Object.values(arrayHashMap);

在这段代码中,我注释了将值推送到数组的部分。我尝试使用“new Set”从最终数组中删除重复项,但我总是将值分配给“obj[item.id].children”。这样可以吗,还是有更好的写法?

预期结果:

[
  id: 10,
  children: [1000, 2000]
, 
  id: 20,
  children: [1000, 2000]
]

谢谢

【问题讨论】:

请添加想要的结果。 @NinaScholz 我添加了预期结果。 【参考方案1】:

您可以按id 分组,如果值不存在,则检查数组,然后推送该值。

const
    data = [ id: 10, children: [1000] ,  id: 10, children: [2000] ,  id: 20, children: [1000] ,  id: 20, children: [1000, 2000] ,  id: 20, children: [2000] ],
    result = Object.values(data.reduce((r,  id, children ) => 
        r[id] ??=  id, children: [] ;
        children.forEach(v => 
            if (!r[id].children.includes(v)) r[id].children.push(v);
        )
        return r;
    , ));

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

【参考方案2】:

使用Array#prototype#reduce 对数组进行归约并在 children 属性上初始化一个集合,然后继续添加到集合中,最后将集合映射回数组。

const arrayOfObjects = [
    id: 10,
    children: [1000]
  ,
  
    id: 10,
    children: [2000]
  ,
  
    id: 20,
    children: [1000]
  ,
  
    id: 20,
    children: [1000, 2000]
  ,
  
    id: 20,
    children: [2000]
  ,
];

const result = Object.values(
    arrayOfObjects.reduce((r, c) => 
      r[c.id] = r[c.id] || 
        id: c.id,
        children: new Set()
      ;

      c.children.forEach((item) => r[c.id].children.add(item));
      return r;
    , Object.create(null))
  )
  .map((x) => (
    id: x.id,
    children: [...x.children]
  ));

console.log(result);

【讨论】:

【参考方案3】:

const arr = [
  
    id: 10,
    children: [1000],
  ,
  
    id: 10,
    children: [2000],
  ,
  
    id: 20,
    children: [1000],
  ,
  
    id: 20,
    children: [1000, 2000],
  ,
  
    id: 20,
    children: [2000],
  ,
];
let result = arr.reduce((acc, i) => 
  let obj = acc.find((a) => a.id === i.id);
  obj ? (obj.children = [...new Set(obj.children.concat(i.children))]): acc.push(i);
  return acc;
, []);

console.log(result);

【讨论】:

【参考方案4】:

你可以试试这个小提琴:https://jsfiddle.net/d0kboywv/2/

const arrayOfObjects = [
  
    id: 10,
    children: [1000]
  ,
  
    id: 10,
    children: [2000]
  ,
  
    id: 20,
    children: [1000]
  ,
  
    id: 20,
    children: [1000, 2000, 3000]
  ,
  
    id: 20,
    children: [2000, 4000]
  ,
];

let mappedArray = new Map(arrayOfObjects.map(o => [o.id, ] ));
for (let obj of arrayOfObjects) 
    let child = mappedArray.get(obj.id);
    for (let [key, val] of Object.entries(obj.children)) 
        child[key] = (child[key] || new Set).add(val);
    

let result = Array.from(mappedArray.entries(), ([id, child]) => ( 
    id, 
    children: [...new Set(Object.entries(child).map(([k, v]) => 
        [...v]
    ).reduce((a, b) => a.concat(b), []))].sort()
));
console.log(result);

它为我完成了这项工作!

【讨论】:

【参考方案5】:

您可以临时将数据结构转换为更简单

const objectOfArray = ; 你的身份是关键,你的孩子是价值

我使用名称 initialData 来引用您的数组

  const objectOfArray = ;
  initialData.forEach(e => 
    if (objectOfArray[e.id] 
      objectOfArray[e.id].push(...e.children);
     else 
      objectOfArray[e.id] = [...e.children];
    
  );


  const result = Object.entries(objectOfArray).map(([id, children]) => 
    return 
      id,
      children: children.filter((e, i) => i === chilren.indexOf(i)),
    
  );

【讨论】:

【参考方案6】:

您还可以通过运行以下代码来实现预期的输出

makeMapping = ;
for (let obj of arrayOfObjects) 
    makeMapping[obj.id] = ...obj, children: [...new Set([...obj.children, ...(makeMapping[obj.id]?.children || [])])];

console.log(Object.values(makeMapping));

【讨论】:

【参考方案7】:

我不知道“更好”,但也许更简洁:

const arrayOfObjects = [
    id: 10,
    children: [1000]
  ,
  
    id: 10,
    children: [2000]
  ,
  
    id: 20,
    children: [1000]
  ,
  
    id: 20,
    children: [1000, 2000]
  ,
  
    id: 20,
    children: [2000]
  ,
];

const arrayHashmap = arrayOfObjects.reduce((obj, 
  id,
  children
) => (
  ...obj,
  [id]: 
    id,
    children: [...new Set([
      ...obj[id]?.children ?? [],
      ...children
    ])]
  
), )

const result = Object.values(arrayHashmap);
console.log(result)

编辑:哎呀,“整洁”按钮改变了语义。固定。

【讨论】:

以上是关于从对象数组中的嵌套数组中删除重复项的主要内容,如果未能解决你的问题,请参考以下文章

从数组中删除重复的对象

删除嵌套组中的重复项

javascript 从javascript中的对象数组中删除重复项

删除数组中的重复项

从 GeoFire 对象数组中删除重复项 [重复]

从数组中删除重复项时出现超出范围异常