合并对象数组中的重复项,并精简嵌套数组

时间:2020-07-19 20:51:46

标签: javascript

我有一个包含重复项的对象数组。 我需要在保留嵌套项目对象的同时删除重复项。

为了清楚起见,这就是我的源数组的样子:

const src = [
  {
    id: '5f10b85e145d7163d818066e',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [
      {
        id: '5f10b8f6145d7163d8180672',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
      },
    ],
  },
  {
    id: '5f10b856145d7163d818066d',
    name: 'Product 1',
    vendor: 'Vendor 2',
    instances: [
      {
        id: '5f10b8c5145d7163d8180671',
        operatingSystem: 'Microsoft Windows 2012R2',
        environment: 'Prod',
        version: '4.1',
        notes: '',
      },
    ],
  },
  {
    id: '5f10b85e145d7163d818066e',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [
      {
        id: '5f10b8f6145d7163d8180672',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
      },
    ],
  },
];
Product 1中的

Vendor 1(具有相同的id)是重复的。 我需要将重复项的实例与第一项合并。

结果数组应如下所示:

const target = [
  {
    id: '5f10b85e145d7163d818066e',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [
      {
        id: '5f10b8f6145d7163d8180672',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
      },
      {
        id: '5f10b8f6145d7163d8180672',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
      },
    ],
  },
  {
    id: '5f10b856145d7163d818066d',
    name: 'Product 1',
    vendor: 'Vendor 2',
    instances: [
      {
        id: '5f10b8c5145d7163d8180671',
        operatingSystem: 'Microsoft Windows 2012R2',
        environment: 'Prod',
        version: '4.1',
        notes: '',
      },
    ],
  },
];

5 个答案:

答案 0 :(得分:1)

您可以使用Map保留ID和对象的首次出现。

然后使用filter函数检查是否已添加ID。

const src = [
    { id: 'foo', name: 'Product 1', instances: [{ key: 'value a' }] },
    { id: 'bar', name: 'Product 2', instances: [{ key: 'value b' }] },
    { id: 'foo', name: 'Product 1', instances: [{ key: 'value c' }] }
];

const unique = new Map();

const target = src.filter((product) => {
    if (unique.has(product.id)) {
        unique.get(product.id).instances.push(...product.instances);
        return false;
    }

    unique.set(product.id, product);
    return true;
});

console.log(target);

答案 1 :(得分:1)

您可以使用Array.prototype.reduce()遍历源数组并建立Map,其中id被用作键,因此一旦复制id,就可以推送实例将当前对象的“对象”放入现有条目,否则设置新条目。 Map准备就绪后,您只需使用Map.prototype.values()提取其值:

const src = [{id:'5f10b85e145d7163d818066e',name:'Product 1',vendor:'Vendor 1',instances:[{id:'5f10b8f6145d7163d8180672',operatingSystem:'Microsoft Windows 2016',environment:'Prod',version:'4.0',notes:'',},],},{id:'5f10b856145d7163d818066d',name:'Product 1',vendor:'Vendor 2',instances:[{id:'5f10b8c5145d7163d8180671',operatingSystem:'Microsoft Windows 2012R2',environment:'Prod',version:'4.1',notes:'',},],},{id:'5f10b85e145d7163d818066e',name:'Product 1',vendor:'Vendor 1',instances:[{id:'5f10b8f6145d7163d8180672',operatingSystem:'Microsoft Windows 2016',environment:'Prod',version:'4.0',notes:'',},],},],

      result = [...src
        .reduce((r, o) => {
          const dupe = r.get(o.id)
          dupe ? 
          dupe.instances.push(...o.instances) : 
          r.set(o.id, o)
          return r
        }, new Map())
        .values()
      ]
      
console.log(result)
.as-console-wrapper{min-height:100%;}

答案 2 :(得分:1)

有很多解决方法。这是一个。

const src = [{
    id: '5f10b85e145d7163d818066e',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [{
      id: '5f10b8f6145d7163d8180672',
      operatingSystem: 'Microsoft Windows 2016',
      environment: 'Prod',
      version: '4.0',
      notes: '',
    }, ],
  },
  {
    id: '5f10b856145d7163d818066d',
    name: 'Product 1',
    vendor: 'Vendor 2',
    instances: [{
      id: '5f10b8c5145d7163d8180671',
      operatingSystem: 'Microsoft Windows 2012R2',
      environment: 'Prod',
      version: '4.1',
      notes: '',
    }, ],
  },
  {
    id: '5f10b85e145d7163d818066e',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [{
      id: '5f10b8f6145d7163d8180672',
      operatingSystem: 'Microsoft Windows 2016',
      environment: 'Prod',
      version: '4.0',
      notes: '',
    }, ],
  },
];

function deDupe(input) {
  let result = [];
  let productMap = {};
  input.forEach((product, idx) => {
    if (!productMap[product.id]) {
      productMap[product.id] = input[idx];
    } else {
      productMap[product.id].instances.push(...input[idx].instances);
    }
  });

  return Object.values(productMap)
}

console.log(deDupe(src));

答案 3 :(得分:1)

您可以使用reduce,然后用Object.values包装响应,以删除由reduce添加的键

const src = [ { id: '5f10b85e145d7163d818066e', name: 'Product 1', vendor: 'Vendor 1', instances: [ { id: '5f10b8f6145d7163d8180672', operatingSystem: 'Microsoft Windows 2016', environment: 'Prod', version: '4.0', notes: '', }, ], }, { id: '5f10b856145d7163d818066d', name: 'Product 1', vendor: 'Vendor 2', instances: [ { id: '5f10b8c5145d7163d8180671', operatingSystem: 'Microsoft Windows 2012R2', environment: 'Prod', version: '4.1', notes: '', }, ], }, { id: '5f10b85e145d7163d818066e', name: 'Product 1', vendor: 'Vendor 1', instances: [ { id: '5f10b8f6145d7163d8180672', operatingSystem: 'Microsoft Windows 2016', environment: 'Prod', version: '4.0', notes: '', }, ], }, ];
var res=src.reduce((a,c)=>{
  if (!a[c.id]) a[c.id]= {...a[c.id],...c}
  else {
    a[c.id].instances.push(c.instances)
    a[c.id].instances=[].concat(...a[c.id].instances);
  }
return a
},{})
console.log(Object.values(res))

答案 4 :(得分:0)

使用从id到类似这样的对象的映射:

const map = {}
...
// Given object:
if (object.id in map) {
  const object_master = map[object.id]
  object_master.instances.push(...object.instances)
} else map[object.id] = object