【问题标题】:How to group objects by nested child objects of array in array如何通过数组中数组的嵌套子对象对对象进行分组
【发布时间】:2020-04-04 19:47:07
【问题描述】:

我一直有这个小问题,试图在地毯下扫除。

我正在调用一个产品 API,每个产品都有一个键 categories,其值是一组地图。尝试按类别对这些进行分类。

这是我的 API 响应示例

[
  {
    "name": "Product one",
    "categories": [
      {
        "id": 1,
        "name": "Category One"
      }
    ]
  },
  {
    "name": "Product Two",
    "categories": [
      {
        "id": 1,
        "name": "Category One"
      },
      {
        "id": 2,
        "name": "Category two"
      }
    ]
  }
]

我编写的代码如下:

 function groupBy(arr) {
      let categories = [];
      arr.forEach(el => {
        el.categories.forEach(c => {
          // Skapa ny kategori om inte redan existerar
          if (!categories.includes(c.id)) {
            categories.push({
              name: c.name,
              id: c.id,
              products: [el]
            });
          } else {
            // Lägg till produkt i existerande kategori
            categories.forEach(_c => {
              if (_c.id === c.id) {
                _c.products.push(el)
              }
            })
          }
        });
      });

      return categories;
    }

groupBy(arr);

我觉得我有点过头了,想要的结果当然是没有任何重复的类别,产品应该被推入products[]。

【问题讨论】:

  • 预期的 json 结果是什么?
  • 您想根据类别对产品进行分组吗?

标签: javascript arrays underscore.js lodash


【解决方案1】:

使用map-reduce 可以做到。

const data = [{"name":"Product one","categories":[{"id":1,"name":"Category One"}]},{"name":"Product Two","categories":[{"id":1,"name":"Category One"},{"id":2,"name":"Category two"}]}];

function categoriesList(list = []) {
  return Object.values(
    list.reduce((arr, product) => {
      product.categories.forEach((cat) => {
        if (!arr[cat.id]) arr[cat.id] = { ...cat, products: [] };
        arr[cat.id].products.push(product);
      });
      return arr;
    }, {})
  );
}
console.log(JSON.stringify(categoriesList(data), null, 4));
.as-console {
  min-height: 100% !important;
}

.as-console-row {
  color: blue !important;
}

【讨论】:

    【解决方案2】:

    您可以通过首先迭代产品以将其分配给每个类别来做到这一点。为了防止重复,您要使用地图或集合;在这里,我使用 javascript 对象作为地图。一旦你有了它,你可以通过在地图对象上使用 Object.values() 将它转换为你想要的数组

    const groupProductsByCategory = (products) => {
      // reduce down each product into a category map
      const productsGroupedByCategory = products.reduce((categories, product) => {
        // insert the current product into each of the categories it contains
        product.categories.forEach(category => {
          // if the category exists in the map, we just need to append the current product
          if (category.id in categories)
            categories[category.id].products.push(product)
          else // otherwise, create a new category object with the current product
          categories[category.id] = ({ ...category, products: [product] })
        })
        return categories
      }, ({}))
    
      // convert the object into an array of objects
      return Object.values(productsGroupedByCategory)
    }
    

    【讨论】:

    • 非常有据可查的答案,而且很快! Muchos gracias @RobBrander
    猜你喜欢
    • 2020-09-17
    • 2018-02-25
    • 2018-05-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    相关资源
    最近更新 更多