How to use Lodash to merge two collections based on a key?

Second highest voted answer doesn’t do proper merge. If second array contains an unique property, it is not taken into account.

This approach does a proper merge.

Lodash

var a = [
  { userId:"p1", item:1},
  { userId:"p2", item:2},
  { userId:"p3", item:4}
];

var b = [
  { userId:"p1", profile:1},
  { userId:"p2", profile:2},
  { userId:"p4", profile:4}
];
var merged = _.merge(_.keyBy(a, 'userId'), _.keyBy(b, 'userId'));
var values = _.values(merged);
console.log(values);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

ES6+

// from https://stackoverflow.com/a/34749873/80766
const mergeDeep = (target, ...sources) => {
  if (!sources.length) return target;
  const source = sources.shift();

  if (target instanceof Object && source instanceof Object) {
    for (const key in source) {
      if (source[key] instanceof Object) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

const a = [
  { userId:"p1", item:1},
  { userId:"p2", item:2},
  { userId:"p3", item:4}
];

const b = [
  { userId:"p1", profile:1},
  { userId:"p2", profile:2},
  { userId:"p4", profile:4}
];


const aKeyed = a.reduce((acc, cur) => ({ ...acc, [cur.userId]: cur }), {});
const bKeyed = b.reduce((acc, cur) => ({ ...acc, [cur.userId]: cur }), {});
const merged = mergeDeep(aKeyed, bKeyed);
const values = Object.values(merged);
console.log(values);

Leave a Comment