-1

What would be the most efficient way to group items by the name key in a nested array/object?

The main array looks something like this here:

let arr = [
  {
    id: 123,
    compensatedItems: [
      {
        name: 'Random item 1',
        id: '123512',
        reason: 'missing_items',
      },
      {
        name: 'Random item 1',
        id: '123512',
        reason: 'missing_items',
      },
      {
        name: 'Random item 1',
        id: '123512',
        reason: 'missing_items',
      },
      {
        name: 'Another random item',
        id: '24122',
        reason: 'missing_items',
      },
      {
        name: 'Another random item',
        id: '24122',
        reason: 'missing_items',
      },
    ],
  },
  {
    id: 341,
    compensatedItems: [
      {
        name: 'Random item 1',
        id: '123512',
        reason: 'missing_items',
      },
      {
        name: 'Random item 1',
        id: '123512',
        reason: 'missing_items',
      },
      {
        name: 'Another random item',
        id: '24122',
        reason: 'missing_items',
      },
    ],
  },
];

Where you have a main array that has multiple objects, and each object has a compensatedItems array with additional objects in it.

I'd like to get the compensatedItems grouped by the name so that the end result would look something like

let res = [
  {
    name: 'Random item 1',
    id: '123512',
    reason: 'missing_items',
    count: 5,
  },
  {
    name: 'Another random item',
    id: '24122',
    reason: 'missing_items',
    count: 3,
  },
];

Its one of those days when nothing makes sense and having a hard time coming up with an efficient solution without looping 1000 times. 🤦🏼‍♂️

Thanks!

1
  • 1
    why not use two nested loops? what goes wrong? Commented Jun 17, 2022 at 13:33

2 Answers 2

1

You can reduce a flatted array with the compensated items as follows:

const arr = [  {    id: 123,    compensatedItems: [      {        name: 'Random item 1',        id: '123512',        reason: 'missing_items',      },      {        name: 'Random item 1',        id: '123512',        reason: 'missing_items',      },      {        name: 'Random item 1',        id: '123512',        reason: 'missing_items',      },      {        name: 'Another random item',        id: '24122',        reason: 'missing_items',      },      {        name: 'Another random item',        id: '24122',        reason: 'missing_items',      },    ],  },  {    id: 341,    compensatedItems: [      {        name: 'Random item 1',        id: '123512',        reason: 'missing_items',      },      {        name: 'Random item 1',        id: '123512',        reason: 'missing_items',      },      {        name: 'Another random item',        id: '24122',        reason: 'missing_items',      },    ],  },],
      compensatedItems = arr.flatMap(({compensatedItems}) => compensatedItems),
      result = Object.values(compensatedItems.reduce((a, {name, ...rest}) => {
        (a[name] || (a[name] = {...rest, name, count: 0})).count++;
        return a;
      }, Object.create(null)));

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

With the flatted array, we can reduce it with your preferred counting logic.

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

Comments

1

You could get an array of compensatedItems and use your favourite grouping/counting algorithm/function.

const
    data = [{ id: 123, compensatedItems: [{ name: 'Random item 1', id: '123512', reason: 'missing_items' }, { name: 'Random item 1', id: '123512', reason: 'missing_items' }, { name: 'Random item 1', id: '123512', reason: 'missing_items' }, { name: 'Another random item', id: '24122', reason: 'missing_items' }, { name: 'Another random item', id: '24122', reason: 'missing_items' }] }, { id: 341, compensatedItems: [{ name: 'Random item 1', id: '123512', reason: 'missing_items' }, { name: 'Random item 1', id: '123512', reason: 'missing_items' }, { name: 'Another random item', id: '24122', reason: 'missing_items' }] }],
    countBy = (array, key) => Object.values(array.reduce((r, o) => {
        r[o[key]] ??= { ...o, count: 0 };
        r[o[key]].count++;
        return r;
    }, {})),
    result = countBy(
        data.flatMap(({ compensatedItems }) => compensatedItems),
        'name'
    );

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.