Home > Software engineering >  merge an array of objects where one property is the same, while transferring the unique values of an
merge an array of objects where one property is the same, while transferring the unique values of an

Time:10-16

I have an array of objects in which most of the properties may be duplicates of each other, but one value may differ:

const originalArray = [
  { id: 1, name: 'x', 'description': 'x', url: 'y' },
  { id: 2, name: 'x', 'description': 'x', url: 'z' }
]

I want to dedupe this array based on a difference of name, but retain the URL differences as an array in the deduped array:

const dedupedArray = [
  { id: 1, name: 'x', 'description': 'x', url: ['y','z'] },
]
function removeDuplicatesByProperty(keyFn, array) {
  const mySet = new Set();
  return array.filter(function (x) {
    const key = keyFn(x),
      isNew = !mySet.has(key);
    if (isNew) mySet.add(key);
    return isNew;
  });
}

const dedupedArray = removeDuplicatesByProperty((x) => x.name, originalArray);

CodePudding user response:

You can use Array.reduce:

const originalArray = [
  { id: 1, name: 'x', 'description': 'x', url: 'y' },
  { id: 2, name: 'x', 'description': 'x', url: 'z' }
]

const res = originalArray.reduce((a,b) => {
  const found = a.find(e => e.name == b.name);
  return found ? found.url.push(b.url) : a.push({...b, url:[b.url]}), a;
}, [])

console.log(res)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Reduce the array to a Map, and merge duplicates using a mergeFn. Convert the Map.values() iterator back to an array using Array.from() or array spread:

const originalArray = [
  { id: 1, name: 'x', 'description': 'x', url: 'y' },
  { id: 2, name: 'x', 'description': 'x', url: 'z' }
]

const dedupeMerge = (keyFn, mergeFn, array) => Array.from(
  array.reduce((acc, o) => {
    const key = keyFn(o);
    
    if(!acc.has(key)) return acc.set(key, o);
    
    return acc.set(key, mergeFn(acc.get(key), o));
  }, new Map()).values()
);

const dedupedArray = dedupeMerge(
  x => x.name, 
  (o1, o2) => ({ ...o1, url: [o1.url, o2.url].flat() }),
  originalArray
);

console.log(dedupedArray);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related