2

I have this array of objects:

[
  {
    "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
      }
    ]
  }
]

What I wanted to achieve is to group by date, name and the number of items. The desired result would be:

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

If it has the same date but different name like:

[
  {
    "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
      }
    ]
  }
]

The desired result would be:

[
  {
    "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
      }
    ]
  }
]

I've tried using lodash and array reduce method but still unable to get the desired result:

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]
  };
});

How to achieve this one? Need your inputs. Thanks!

2 Answers 2

1

You can achieve this as:

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);

Sign up to request clarification or add additional context in comments.

Comments

1
  • Using Array#reduce, iterate over the list while updating a Map where the key is <date>-<name> and the value is the grouped object (having all items of this key).
  • Using Array#map, iterate over the above grouped objects. For each object, we need to group its items by item_id while updating the count.

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) );

1 Comment

Thanks for taking the time to answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.