首页 > 解决方案 > 使用 Javascript 操作对象并合并相似数据

问题描述

我正在努力处理 Javascript 对象,并感谢您的建议:

我有以下对象:

const source = {
  id: '1',
  name: 'Customer A',
  projects: [
    {
      id: '10',
      name: 'Project 2',
      description: 'Project 2 description',
      products: [
        {
          id: '100',
          name: 'Product 1',
          vendor: 'Vendor 1',
          instances: [
            {
              id: '1000',
              operatingSystem: 'Microsoft Windows 2012R2',
              environment: 'Prod',
              version: '4.1',
              notes: '',
            },
          ],
        },
        {
          id: '200',
          name: 'Product 2',
          vendor: 'Vendor 2',
          instances: [
            {
              id: '2000',
              operatingSystem: 'Microsoft Windows 2016',
              environment: 'Prod',
              version: '4.0',
              notes: '',
            },
          ],
        },
      ],
    },
    {
      id: '20',
      name: 'Project 1',
      description: 'Project 1 description',
      products: [
        {
          id: '200',
          name: 'Product 2',
          vendor: 'Vendor 2',
          instances: [
            {
              id: '2000',
              operatingSystem: 'Microsoft Windows 2016',
              environment: 'Prod',
              version: '4.0',
              notes: '',
            },
            {
              id: '3000',
              operatingSystem: 'RedHat Linux 7',
              environment: 'Prod',
              version: '3.12',
              notes: '',
            },
          ],
        },
      ],
    },
  ],
};

我想从上面的对象中提取按产品分组的实例列表(这部分工作正常):

const products = [
  {
    id: '100',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [
      {
        id: '1000',
        operatingSystem: 'Microsoft Windows 2012R2',
        environment: 'Prod',
        version: '4.1',
        notes: '',
      },
    ],
  },
  {
    id: '200',
    name: 'Product 2',
    vendor: 'Vendor 2',
    instances: [
      {
        id: '2000',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
      },
      {
        id: '2000',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
      },
      {
        id: '3000',
        operatingSystem: 'RedHat Linux 7',
        environment: 'Prod',
        version: '3.12',
        notes: '',
      },
    ],
  },
];

以上是通过映射项目、扁平化产品阵列和减少结果来实现的。我的下一个目标是为每个实例添加与其关联的项目。我需要附上项目 ID 和项目名称。在上面的示例中,您可以看到具有 '2000' id 的实例与 2 个项目相关联,因此,预期结果应如下所示:

const expected = [
  {
    id: '100',
    name: 'Product 1',
    vendor: 'Vendor 1',
    instances: [
      {
        id: '1000',
        operatingSystem: 'Microsoft Windows 2012R2',
        environment: 'Prod',
        version: '4.1',
        notes: '',
        projects: [
          {
            id: '10',
            name: 'Project 2',
          },
        ],
      },
    ],
  },
  {
    id: '200',
    name: 'Product 2',
    vendor: 'Vendor 2',
    instances: [
      {
        id: '2000',
        operatingSystem: 'Microsoft Windows 2016',
        environment: 'Prod',
        version: '4.0',
        notes: '',
        projects: [
          {
            id: '10',
            name: 'Project 2',
          },
          {
            id: '20',
            name: 'Project 1',
          },
        ],
      },
      {
        id: '3000',
        operatingSystem: 'RedHat Linux 7',
        environment: 'Prod',
        version: '3.12',
        notes: '',
        projects: [
          {
            id: '20',
            name: 'Project 1',
          },
        ],
      },
    ],
  },
];

我试图通过几个“forEach”循环、映射等来操作数组,但没有成功。希望您能提出如何实现的想法。

标签: javascript

解决方案


const { inspect } = require('util'); // if Node.js

const source = {
  id: '1', name: 'Customer A', projects: [
    {
      id: '10', name: 'Project 2', description: 'Project 2 description', products: [
        {
          id: '100', name: 'Product 1', vendor: 'Vendor 1', instances: [
            { id: '1000', operatingSystem: 'Microsoft Windows 2012R2', environment: 'Prod', version: '4.1', notes: '', },
          ],
        },
        {
          id: '200', name: 'Product 2', vendor: 'Vendor 2', instances: [
            { id: '2000', operatingSystem: 'Microsoft Windows 2016', environment: 'Prod', version: '4.0', notes: '', },
          ],
        },
      ],
    },
    {
      id: '20', name: 'Project 1', description: 'Project 1 description', products: [
        {
          id: '200', name: 'Product 2', vendor: 'Vendor 2', instances: [
            { id: '2000', operatingSystem: 'Microsoft Windows 2016', environment: 'Prod', version: '4.0', notes: '', },
            { id: '3000', operatingSystem: 'RedHat Linux 7', environment: 'Prod', version: '3.12', notes: '', },
          ],
        },
      ],
    },
  ],
};

const projectToIdMap = source.projects.reduce((projectToIdMap, { name, products }) => {
  projectToIdMap[name] = [];
  products.forEach(({ instances }) => {
    instances.forEach(({ id }) => {
      projectToIdMap[name].push(id);
    });
  });
  return projectToIdMap;
}, {});

const products = [
  {
    id: '100', name: 'Product 1', vendor: 'Vendor 1', instances: [
      { id: '1000', operatingSystem: 'Microsoft Windows 2012R2', environment: 'Prod', version: '4.1', notes: '', },
    ],
  },
  {
    id: '200', name: 'Product 2', vendor: 'Vendor 2', instances: [
      { id: '2000', operatingSystem: 'Microsoft Windows 2016', environment: 'Prod', version: '4.0', notes: '', },
      { id: '2000', operatingSystem: 'Microsoft Windows 2016', environment: 'Prod', version: '4.0', notes: '', },
      { id: '3000', operatingSystem: 'RedHat Linux 7', environment: 'Prod', version: '3.12', notes: '', },
    ],
  },
];

products.forEach(({ instances }) => {
  instances.forEach(instance => {
    instance.projects = [];
    const { id } = instance;
    Object.entries(projectToIdMap).forEach(([project, os], i) => {
      if (projectToIdMap[project].includes(id)) {
        instance.projects.push({ id: (i + 1) * 10, project });
      }
    });
  });
});

console.log(inspect(products, false, null, true)); // if Node.js

这不会删除重复的Microsoft Windows 2016条目,但我相信您可以从这里获取它。


推荐阅读