user16172269
user16172269

Reputation:

Merge values of objects with same keys into an array using lodash

I have an array of objects which looks like this:

const childrens = [
    { orderName: "#1004" },
    { orderName: "#1006" },
    { orderName: "#1007" },
    { orderName: "#1005" },
    { deliveryDate: "25-25-25" },
    { signature: "xq" },
  ];

I want this to be converted into object and have values of same keys as an array of values like this

{
  orderName: [ '#1004', '#1006', '#1007', '#1005' ],
  deliveryDate: [ '25-25-25' ],
  signature: [ 'xq' ]
}

The way i'm doing this right now is by using a reduce function like this

_.reduce(
    childrens,
    (acc, cur) => {
      const pairs = _.chain(cur).toPairs().flatten().value();

      if (acc[pairs[0]] === undefined) {
        acc[pairs[0]] = [pairs[1]];
      } else {
        acc[pairs[0]].push(pairs[1]);
      }

      return acc;
    },
    {},
  );

I'm wondering if there's a cleaner way using built-in lodash functions?

Upvotes: 0

Views: 1851

Answers (4)

DecPK
DecPK

Reputation: 25408

You can simply get the result using vanilla JS using reduce and Object.entries

(acc[prop] = acc[prop] ?? []).push(value);

const childrens = [
  { orderName: "#1004" },
  { orderName: "#1006" },
  { orderName: "#1007" },
  { orderName: "#1005" },
  { deliveryDate: "25-25-25" },
  { signature: "xq" },
];

const result = childrens.reduce((acc, curr) => {
  const [[prop, value]] = Object.entries(curr);
  (acc[prop] = acc[prop] ?? []).push(value);
  return acc;
}, {});

console.log(result);

Upvotes: 0

SimonR
SimonR

Reputation: 1268

Something like this will work on modern JS platforms (added bonus, you don't need lodash to use reduce). Essentially:

  • loop over each item in childrens
  • get the key(s) for that object
  • loop over the key(s)
    • if result doesn't have that key set it to an empty array
    • push the value for the key to the relevant array on the result
const desiredOutput = childrens.reduce(
  (acc, current) => {
    const keys = Object.keys(current);
    keys.forEach(key => {
      if (!acc[key]) {
        acc[key] = [];
      }
      acc[key].push(current[key]);
    });
    return acc;
  },
  {}
);

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 192006

You can use _.mergeWith() with array spread. When merging 2 values, check if the 1st (a) is still undefined (the empty object), if so return the 2nd item wrapped in an array, if it exists, use array spread to concat them:

const children = [{"orderName":"#1004"},{"orderName":"#1006"},{"orderName":"#1007"},{"orderName":"#1005"},{"deliveryDate":"25-25-25"},{"signature":"xq"}];

const result = _.mergeWith({}, ...children, (a, b) => 
  _.isUndefined(a) ? [b] : [...a, b]
);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Upvotes: 3

ikhvjs
ikhvjs

Reputation: 5947

If you don't use lodash, you can do like below.

const children = [
  { orderName: "#1004" },
  { orderName: "#1006" },
  { orderName: "#1007" },
  { orderName: "#1005" },
  { deliveryDate: "25-25-25" },
  { signature: "xq" },
];

const output = children.reduce((a, b) => {
  const key = Object.keys(b)[0];
  if (!a[key]) {
    a[key] = [b[key]];
  } else {
    a[key].push(b[key]);
  }
  return a;
}, {});

console.log(output);

Upvotes: 1

Related Questions