Need help understanding the solution for Group Items in Array or Object by Given Value

After having spent a few hours trying to solve This Question, I decided to take a look the solution and I can’t seem to get a part of the solution through my thick skull.

Solution:

const myGroupBy = (collection, q) => {
  collection = Object.values(collection);
  switch (typeof q) {
    case "string":
      return collection.reduce((a, c) => (a[c[q]] = [...(a[c[q]] || []), c], a), {});
    case "function":
      return collection.reduce((a, c) => (a[q(c)] = [...(a[q(c)] || []), c], a), {});
    default:
      const [[k, v]] = Object.entries(q);
      return collection.reduce((a, c) => (a[c[k] === v] = [...(a[c[k] === v] || []), c], a), {});
  }
};

The part I don’t understand: (a[c[q]] = [...(a[c[q]] || []), c], a)

Any help would be greatly appreciated.

Answer

It’s a difficult-to-understand way of adding a new item to an array when the array might not exist yet.

.reduce((a, c) => (a[c[q]] = [...(a[c[q]] || []), c], a), {});

is, unminified:

.reduce((a, c) => {
  const prop = c[q];
  if (!a[prop]) {
    // array doesn't exist yet; create it
    a[prop] = [];
  }
  // it definitely exists now. Now, push the new item to it
  a[prop].push(c);
  // return the accumulator
  return a;
}, {});

The same pattern is being used for the other .reduces here.

.reduce arguably isn’t very appropriate here though, a plain loop would make more sense since the accumulator never changes.

const obj = {};
for (const c of collection) {
  const prop = c[q];
  if (!obj[prop]) {
    // array doesn't exist yet; create it
    obj[prop] = [];
  }
  // it definitely exists now. Now, push the new item to it
  obj[prop].push(c);
}
return obj;

These approaches do mutate the existing arrays on the accumulator instead of reassigning entirely new arrays (like your original code does) – but since the array starts out empty, it won’t have any effect (positive or negative).

Leave a Reply

Your email address will not be published. Required fields are marked *