3

here is a sample example where there are two arrays and we have a merge() to which we pass the arrays. the merge() should return the merged array such that it should merge the objects which have same name.

let arr1 = [
  {
    name: "Person1",
    age: 20
  },
  {
    name: "Person2",
    age: 30
  }
]


let arr2 = [
  {
    name: "Person1",
    email: "person1@mail.com"
  },
  {
    name: "Person3",
    age: 25
  }
]


arr3 = merge(arr1, arr2)

output : 
arr3 should be : 
[
 {
    name: "Person1",
    age: 20,
    email: "person1@mail.com"
  },
   {
    name: "Person2",
    age: 30
  },
   {
    name: "Person3",
    age: 25
  }
]
shubham patil
  • 101
  • 1
  • 1
  • 10
  • 2
    Does this answer your question? [How to merge two arrays in JavaScript and de-duplicate items](https://stackoverflow.com/questions/1584370/how-to-merge-two-arrays-in-javascript-and-de-duplicate-items) – Shatsuki Feb 09 '22 at 11:13
  • 1
    @Shatsuki That question is about merging arrays of strings, this question is about merging an array of objects, where some of the objects themselves might need to be merged. – Nick Parsons Feb 09 '22 at 11:14
  • You may break down the problem into smaller sub-problems. First identify the unique names from both arrays. Then, iterate through the names and pull the corresponding props from both arrays to construct your target array. Will try to post an answer, if possible. – jsN00b Feb 09 '22 at 11:15
  • Can you please provide your attempt so far for the `merge` function? What specifically are you having problems with? – Nick Parsons Feb 09 '22 at 11:16
  • 1
    `name similar` ... similar or the same? the two words are not synonymous – Bravo Feb 09 '22 at 11:18
  • What's the expected behaviour if "Person3" is in arr1 and arr2 with different age values ? – malarres Feb 09 '22 at 11:20
  • @Bravo Update the question, Thanks! – shubham patil Feb 09 '22 at 11:22
  • @malarres it should override. – shubham patil Feb 09 '22 at 11:22

7 Answers7

3

You could take an object as hash table for keeping track of merged objects with same name and return only the values from the hash table.

const
    merge = (...arrays) => {
        const merged = {};
        
        arrays.forEach(data =>
            data.forEach(o => Object.assign(merged[o.name] ??= {}, o))
        );
        
        return Object.values(merged);
    },
    array1 = [{ name: "Person1", age: 20 }, { name: "Person2", age: 30 }],
    array2 = [{name: "Person1", email: "person1@mail.com" }, { name: "Person3", age: 25 }],
    result = merge(array1, array2);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you for the answer, would you please help me to understand what `??=` operator stands for in `Object.assign(merged[o.name] ??= {}, o)`? – shubham patil Feb 10 '22 at 12:23
  • it is a [logical nullish assignment `??=`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment). that means, if the lhs (left hand side) is null or undefined, the rhs gets assigned. – Nina Scholz Feb 11 '22 at 19:13
2

You can use lodash for that

let arr1 = [
  {
    name: "Person1",
    age: 20
  },
  {
    name: "Person2",
    age: 30
  }
]


let arr2 = [
  {
    name: "Person1",
    email: "person1@mail.com"
  },
  {
    name: "Person3",
    age: 25
  }
]


arr3 = _.merge(_.keyBy(arr1, 'name'), _.keyBy(arr2, 'name'));

console.log(arr3)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Danil Perestoronin
  • 1,063
  • 1
  • 7
  • 9
0

The map part covers every item in arr1, so you can add it as is or merge with the ones both in arr1 and arr2. Then you need a final pass to add those that are in arr2 but not in arr1

let arr1 = [
  {
    name: "Person1",
    age: 20
  },
  {
    name: "Person2",
    age: 30
  }
]


let arr2 = [
  {
    name: "Person1",
    email: "person1@mail.com"
  },
  {
    name: "Person3",
    age: 25
  }
]

const merge = (a1,a2) => {

return a1.map( (x) => {
  const y = a2.find( item => x.name === item.name);
  if (y) {
    return Object.assign({},x,y);
  } else
    return x
}).concat(a2.filter(item => a1.every( x => x.name !== item.name)));




}

arr3 = merge(arr1, arr2)

console.log(arr3)
malarres
  • 2,941
  • 1
  • 21
  • 35
0

We can convert the arrays into objects for better time complexity and merge them using a spread operator and generate the array at the end.

let arr1 = [
  {
    name: "Person1",
    age: 20
  },
  {
    name: "Person2",
    age: 30
  }
]


let arr2 = [
  {
    name: "Person1",
    email: "person1@mail.com"
  },
  {
    name: "Person3",
    age: 25
  }
]
function merge(arr1, arr2){
  const merged_dict = {}
  const r_arr = []
  const arr = [...arr1,...arr2]
  arr.forEach(ele => {
    if(merged_dict[ele.name]){
      merged_dict[ele.name] = {...merged_dict[ele.name],...ele};
    }
    else{
      merged_dict[ele.name] = ele;
    }
  });
  for(let key in merged_dict){
    r_arr.push(merged_dict[key])
  }
  return r_arr
}

arr3 = merge(arr1, arr2)
console.log(arr3)
Abishek Kumar
  • 519
  • 5
  • 13
0

Try this :

let arr1 = [{
    name: "Person1",
    age: 20
}, {
    name: "Person2",
    age: 30
}];
let arr2 = [{
    name: "Person1",
    email: "person1@mail.com"
}, {
    name: "Person3",
    age: 25
}];
function copy(source, destination) {
    for (let prop in source) {
        destination[prop] = source[prop];
    }
}
function merge(arr1, arr2) {
    let newArray = [];
    for (let i = 0, obj1; obj1 = arr1[i]; ++i) {
        let obj = {};
        copy(obj1, obj);
        for (let j = 0, obj2; obj2 = arr2[j]; ++j) {
            if (obj1.name === obj2.name) {
                copy(obj2, obj);
            }
        }
        newArray.push(obj);
    }
    for (let i = 0, obj2; obj2 = arr2[i]; ++i) {
        let here = false;
        for (let j = 0, obj1; obj1 = arr1[j]; ++j) {
            if (obj1.name === obj2.name) {
                here = true;
            }
        }
        if (!here) {
            newArray.push(obj2);
        }
    }
    return newArray;
}
let arr3 = merge(arr1, arr2);
console.log(arr3);
Michaël
  • 14
  • 3
0

    let a = [
               {
                name: "Person15",
                age: 29
               },
               {
              name: "Person20",
          age: 39
         }
        ];;

            let b =  [
               {
                name: "Person1",
                age: 20
               },
               {
              name: "Person2",
          age: 30
         }
        ];

            // b diff a
            let resultA = b.filter(
              elm =>
                !a
                  .map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)),
            );

            // a diff b
            let resultB = a.filter(
              elm =>
                !b
                  .map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)),
            );

            // show merge
            
            const mergedArray = [ ...resultA, ...resultB ]


            const mergedArrays = [ ...b, ...mergedArray ]

            let newData = [
              ...new Map(mergedArrays.map(item => [item.id, item])).values(),
            ];
            console.log(newData);
Deepak Singh
  • 749
  • 4
  • 16
-1
  let arr1 = [
  {
   name: "Person1",
   age: 20
},
 {
 name: "Person2",
 age: 30
 }
]
 
let arr2 = [
 {
  name: "Person1",
  email: "person1@mail.com"
},
 {
   name: "Person3",
   age: 25
  }
] 


var arr3 = [...arr1,...arr2]
  • with this we will have 4 objects instead of 3 output : `0: {name: 'Person1', age: 20}` `1: {name: 'Person2', age: 30}` `2: {name: 'Person1', email: 'person1@mail.com'}` `3: {name: 'Person3', age: 25}` – shubham patil Feb 09 '22 at 11:27