Home > Mobile >  chain lodash _.groupby() with reduce
chain lodash _.groupby() with reduce

Time:07-08

Starting with an array similar to this:

const arr = [
  {id: "id_0", owner: "owner_0", state: "accepted"},
  {id: "id_1", owner: "owner_1", state: "denied"},
  {id: "id_2", owner: "owner_1", state: "accepted"},
  {id: "id_3", owner: "owner_1", state: "accepted"},
  {id: "id_4", owner: "owner_2", state: "pending"},
]

I need to group the data by owner and format the ids. The ids need to be a comma separated string. The state data need not be returned.

const formattedArr = {
  owner_0: {ids: "id_0"},
  owner_1: {ids: "id_1, id_2, id_3"}
  owner_2: {ids: "id_4"}
}

I've been using _.groupBy(arr, 'owner') but not sure how to use a callback or some other map or reduce to format the ids and join them into a string.

Something along the lines of this but preferably using the least amount of loops:

_.chain(arr)
  .groupBy('owner')
  .reduce(group => {
    //format the ids here
    return *formatted ids*
  }
  .value()

CodePudding user response:

So, you actually don't need groupBy in this case. Reduce can easily solve your problem.

const result = arr.reduce((acc, { id, owner }) => {
  if (!acc[owner]) {
    acc[owner] = {ids: id};
    return acc;
  }

  acc[owner].ids  = `, ${id}`;
  return acc;
}, {});

If you prefer lodash it would look almost the same.

_.reduce(arr, (acc, { id, owner }) => {
  if (!acc[owner]) {
    acc[owner] = {ids: id};
    return acc;
  }

  acc[owner].ids  = `, ${id}`;
  return acc;
}, {});

Good luck.

CodePudding user response:

This should do the trick:

_.chain(arr)
  .groupBy('owner')
  .map(o => ({
     owner: o[0].owner,
     ids: o.reduce((acc, curr) => [...acc, curr.id], []).join(', ')
    }))
  .value();

JS Fiddle: https://jsfiddle.net/z3mks4n6/

  • Related