0

Assuming you have the following array:

const units = [
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 2, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 3, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 6, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 7, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 8, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 13, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 14, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 15, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 16, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 25, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 28, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 2, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 3, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 6, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 7, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 8, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 11, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 15, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 25, value: 0},
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 28, value: 0},
]

what is the cleanest and most efficient way to group these such that each object with the same type_id is placed in a sub array like this:

const groupedUnits = [
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 2, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 2, value: 0}
  ],
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 3, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 3, value: 0}
  ],
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 6, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 6, value: 0}
  ],
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 7, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 7, value: 0}
  ],
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 8, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 8, value: 0}
  ],
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 13, value: 0},
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 14, value: 0},
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 15, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 15, value: 0}
  ],
  {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 16, value: 0},
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 25, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 25, value: 0}
  ],
  [
    {unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 28, value: 0},
    {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 28, value: 0}
  ],
  {unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 11, value: 0}
]

I've tried wrestling with reduce to get this to work but so far I'm completely stumped.

edit: I do have this which works:

const typeIds = lines
  .map(u => u.type_id)
  .reduce((types, currentType) => {
    if (types.indexOf(currentType) == -1) {
      return types.concat(currentType);
    } else return types;
  }, []);

const groupedUnits = [];

for (let type of typeIds) {
  let tmpArr = lines.filter(u => u.type_id == type);
  if (tmpArr.length == 1) {
    groupedUnits.push(tmpArr[0]);
  } else groupedUnits.push(tmpArr);
}

but I feel like there must be a cleaner way

Robbie Milejczak
  • 5,664
  • 3
  • 32
  • 65
  • Possible duplicate of [How to group an array of objects by key](https://stackoverflow.com/questions/40774697/how-to-group-an-array-of-objects-by-key) – Herohtar Dec 20 '18 at 21:52
  • @Herohtar that is not at all the result I'm looking for, that is easily solved via `Array.reduce` – Robbie Milejczak Dec 20 '18 at 21:57
  • Instead of an array of arrays, how about a map, with the key being the type_id and the value being an array of the objects? `{ type_id: [{unit_id, value}, {unit_id, value}] }` – Rastalamm Dec 20 '18 at 22:03

2 Answers2

1

You could sort the array and reduce the items and collect same type_id in same arrays.

const
    units = [{ unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 2, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 3, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 6, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 7, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 8, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 13, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 14, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 15, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 16, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 25, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 28, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 2, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 3, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 6, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 7, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 8, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 11, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 15, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 25, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 28, value: 0 }],
    grouped = units
        .sort(({ type_id: a }, { type_id: b }) => a - b)
        .reduce((r, o) => {
            var i = r.length - 1;
            if (!r[i] || r[i].type_id !== o.type_id) {
                r.push(o);
            } else {
                if (!Array.isArray(r[i])) {
                    r[i] = [r[i]];
                }
                r[i].push(o);
            }
            return r;
        }, []);
        
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Without sort, but with taken built in sort for positive integer keys of objects.

const
    units = [{ unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 2, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 3, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 6, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 7, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 8, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 13, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 14, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 15, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 16, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 25, value: 0 }, { unit_id: "33614036-6e8e-c06e-edf2-40f9aaf6224c", type_id: 28, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 2, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 3, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 6, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 7, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 8, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 11, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 15, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 25, value: 0 }, { unit_id: "afc834b6-5a3b-09d1-d548-ff049dc931a9", type_id: 28, value: 0 }],
    grouped = Object.values(units.reduce((r, o) => {
        if (r[o.type_id]) {
            if (!Array.isArray(r[o.type_id])) {
                r[o.type_id] = [r[o.type_id]];
            }
            r[o.type_id].push(o);
        } else {
            r[o.type_id] = o;
        }
        return r;
    }, Object.create(null)));
        
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

How about this:

const units = [
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 2, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 3, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 6, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 7, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 8, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 13, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 14, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 15, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 16, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 25, value: 0 },
  { unit_id: '33614036-6e8e-c06e-edf2-40f9aaf6224c', type_id: 28, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 2, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 3, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 6, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 7, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 8, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 11, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 15, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 25, value: 0 },
  { unit_id: 'afc834b6-5a3b-09d1-d548-ff049dc931a9', type_id: 28, value: 0 },
];

const groupedUnits = Object.values(units.reduce((a, b) => {
  const arr = a[b.type_id] || [];
  return {
    ...a,
    [b.type_id]: [...arr, b],
  };
}, {})).map(n => n.length > 1 ? n : n[0]);
Ricardinho
  • 1,319
  • 13
  • 15