首页 > 解决方案 > 从嵌套数组和嵌套对象数组中过滤对象数组

问题描述

我有以下对象数组

const skus = [
    {
      id: 1,
      features: ["Slim"],
      fields: [
        { label: "Material", value: "Material1" },
        { label: "Type", value: "Type1" }
      ]
    },
    {
      id: 2,
      features: ["Cotton"],
      fields: [
        { label: "Material", value: "Material2" },
        { label: "Type", value: "Type2" }
      ]
    },
    {
      id: 3,
      features: ["Slim"],
      fields: [
        { label: "Material", value: "Material3" },
        { label: "Type", value: "Type1" }
      ]
    }
  ]

我希望预期的输出是

const output = [
    { label: "features", value: ["Slim", "Cotton"] },
    { label: "Material", value: ["Material1", "Material2", "Material3"] },
    { label: "Type", value: ["Type1", "Type2"] }
  ]

我尝试了以下方式

const output = [];

  let featureArr = [];
  let fieldsArr = []
  skus.forEach(e => {
    e.features.forEach(f => {
      featureArr.push(f);
    });
    e.fields.forEach(f => {
      fieldsArr.push({ label: f.label, value: f.value });
    });
  });
  featureArr = _.uniq(featureArr);
  fieldsArr = _.uniqBy(fieldsArr, 'value')
  fieldsArr = _.groupBy(fieldsArr, 'label');

  output.push({ label: 'Features', value: featureArr })

  for (const k in fieldsArr) {
    let valArr = []
    valArr = fieldsArr[k].map(v => v.value)
    output.push({ label: k, value: valArr });
  }

我得到了预期的输出,但这里存在多个循环。有没有办法以更优化的方式编写解决方案。

标签: javascriptarraysjavascript-objects

解决方案


您可以为嵌套属性使用分组函数,其中映射、用于迭代的数组、组和值键被移交。结果是一个包含每个组的所有收集值的映射。

稍后从地图中获取所有唯一值并构建一个新的对象数组。

const
    skus = [{ id: 1, features: ["Slim"], fields: [{ label: "Material", value: "Material1" }, { label: "Type", value: "Type1" }] }, { id: 2, features: ["Cotton"], fields: [{ label: "Material", value: "Material2" }, { label: "Type", value: "Type2" }] }, { id: 3, features: ["Slim"], fields: [{ label: "Material", value: "Material3" }, { label: "Type", value: "Type1" }] }],
    getGrouped = (map, array, key, value) => array.reduce((m, o) =>
        m.set(o[key], [...(m.get(o[key]) || []), o[value]]), map),
    result = Array.from(
        skus.reduce((m, o) =>
            getGrouped(
                m.set('features', [...(m.get('features') || []), ...o.features]),
                o.fields,
                'label',
                'value'
            ),
            new Map
        ),
        ([label, value]) => ({ label, value: [...new Set(value)] })
    );

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


推荐阅读