繁体   English   中英

JavaScript:如何使用嵌套属性对对象数组进行分组?

[英]JavaScript: How to Group Array of Objects with Nested Properties?

我有这个对象数组:

[
  {
    "date": "08/08/2022",
    "name": "Swordsman",
    "items": [
      {
        "item_id": 1,
        "item": {
          "item_name": "Item 1",
        },
        "count": 1
      }
    ]
  },
  {
    "date": "08/08/2022",
    "name": "Swordsman",
    "items": [
      {
        "item_id": 1,
        "item": {
          "item_name": "Item 1",
        },
        "count": 2
      },
      {
        "item_id": 2,
        "item": {
          "item_name": "Item 2",
        },
        "count": 1
      }
    ]
  }
]

我想要实现的是按日期名称项目数进行分组。 期望的结果是:

[
  {
    "date": "08/08/2022",
    "name": "Swordsman",
    "items": [
      {
        "item_id": 1,
        "name": "Item 1",
        "count": 3
      },
      {
        "item_id": 2,
        "name": "Item 2",
        "count": 1
      }
    ]
  }
]

如果日期相同但名称不同,例如:

[
  {
    "date": "08/08/2022",
    "name": "Swordsman",
    "items": [
      {
        "item_id": 1,
        "item": {
          "item_name": "Item 1",
        },
        "count": 1
      }
    ]
  },
  {
    "date": "08/08/2022",
    "name": "Swordsman",
    "items": [
      {
        "item_id": 1,
        "item": {
          "item_name": "Item 1",
        },
        "count": 2
      },
      {
        "item_id": 2,
        "item": {
          "item_name": "Item 2",
        },
        "count": 1
      }
    ]
  },
  {
    "date": "08/08/2022",
    "name": "Archer",
    "items": [
      {
        "item_id": 1,
        "item": {
          "item_name": "Item 1",
        },
        "count": 2
      },
      {
        "item_id": 2,
        "item": {
          "item_name": "Item 2",
        },
        "count": 1
      }
    ]
  }
]

期望的结果是:

[
  {
    "date": "08/08/2022",
    "name": "Swordsman",
    "items": [
      {
        "item_id": 1,
        "name": "Item 1",
        "count": 3
      },
      {
        "item_id": 2,
        "name": "Item 2",
        "count": 1
      }
    ]
  },
  {
    "date": "08/08/2022",
    "name": "Archer",
    "items": [
      {
        "item_id": 1,
        "name": "Item 1",
        "count": 2
      },
      {
        "item_id": 2,
        "name": "Item 2",
        "count": 1
      }
    ]
  }
]

我尝试过使用 lodash 和 array reduce 方法,但仍然无法获得所需的结果:

const groups = data.reduce((groups, data) => {
  const date = data.date;
  if (!groups[date]) {
    groups[date] = [];
  }
  
  groups[date].push(data);
  return groups;
}, {});

const groupArrays = Object.keys(groups).map((date) => {
  return {
    date,
    items: groups[date]
  };
});

如何实现这一目标? 需要你的投入。 谢谢!

您可以通过以下方式实现:

 const arr = [ { date: '08/08/2022', name: 'Swordsman', items: [ { item_id: 1, item: { item_name: 'Item 1', }, count: 1, }, ], }, { date: '08/08/2022', name: 'Swordsman', items: [ { item_id: 1, item: { item_name: 'Item 1', }, count: 2, }, { item_id: 2, item: { item_name: 'Item 2', }, count: 1, }, ], }, { date: '08/08/2022', name: 'Archer', items: [ { item_id: 1, item: { item_name: 'Item 1', }, count: 2, }, { item_id: 2, item: { item_name: 'Item 2', }, count: 1, }, ], }, ]; function addItemsToNewArrFromOld(oldItems, newItemsToAdd) { newItemsToAdd.forEach((o) => { const { item_id, count, item: { item_name: item }} = o; const itemInOldItems = oldItems.find((obj) => obj.item_id === o.item_id); if (itemInOldItems) itemInOldItems.count += o.count; else oldItems.push({ item_id, count, item }); }); } const map = new Map(); arr.forEach(({ date, name, items }) => { const key = `${date}-${name}`; if (map.has(key)) { const objForKeyFound = map.get(key); addItemsToNewArrFromOld(objForKeyFound.items, items); } else { map.set(key, { date, name, items: items.map(({ item_id, item, count }) => ({ item_id, count, item: item.item_name })), }); } }); const result = [...map.values()]; console.log(result);

  • 使用Array#reduce迭代列表,同时更新Map ,其中key<date>-<name>value分组的 object (具有此键的所有items )。
  • 使用Array#map遍历上述分组对象。 对于每个 object,我们需要在更新count时按item_id对其items进行分组。

 const groupByDateAndName = arr => [... arr.reduce((map, { date, name, items = [] }) => { const key = `${date}-${name}`; const { items: prevItems = [] } = map.get(key)?? {}; map.set( key, { date, name, items: [...prevItems, ...items.map(({ item_id, item, count }) => ({ item_id, count, name: item.item_name })) ] } ); return map; }, new Map).values() ]; const groupItemsById = arr => arr.map(e => { const items = [... e.items.reduce((map, { item_id, name, count }) => { const { count: prevCount = 0 } = map.get(item_id)?? {}; map.set(item_id, { item_id, name, count: prevCount + count }) return map; }, new Map).values() ] return {...e, items }; }); const group = (arr = []) => { const list = groupByDateAndName(arr); return groupItemsById(list); } const arr = [ { "date": "08/08/2022", "name": "Swordsman", "items": [ { "item_id": 1, "item": { "item_name": "Item 1" }, "count": 1 } ] }, { "date": "08/08/2022", "name": "Swordsman", "items": [ { "item_id": 1, "item": { "item_name": "Item 1" }, "count": 2 }, { "item_id": 2, "item": { "item_name": "Item 2" }, "count": 1 } ] }, { "date": "08/08/2022", "name": "Archer", "items": [ { "item_id": 1, "item": { "item_name": "Item 1" }, "count": 2 }, { "item_id": 2, "item": { "item_name": "Item 2" }, "count": 1 } ] } ]; console.log( group(arr) );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM