Merging two Javascript objects with similar keys

Viewed 137

I need to merge two objects(obj1, obj2), that happen to share similar keys.

obj1 = {
0:{"Example1": "Example1"},
1:{"Example1": "Example1"},
2:{"Example1": "Example1"}
}

obj2 = {
0:{"Example2": "Example2"},
1:{"Example2": "Example2"},
2:{"Example2": "Example2"}
}

Expected result:

obj3 = {
0:{"Example1": "Example1"},
1:{"Example1": "Example1"},
2:{"Example1": "Example1"},
3:{"Example2": "Example2"},
4:{"Example2": "Example2"},
5:{"Example2": "Example2"},
}

Usual approach when merging two objects:

const obj3 = Object.assign({}, obj1, obj2);

Problem: They do share many keys, as such, in obj3, only the contents of obj2 are going to be found.

My approach:

let obj3= Object.assign({}, obj1);
for(let i=0; i<obj2.length; i++) {
    obj3[obj3.length + i] = obj2[i];
}

Question: Is there, another more elegant, pre-defined way of merging two objects with similar keys?

3 Answers

Although I still think obj1 and obj2 should be arrays...

const obj1 = {
  0:{"Example1": "Example1"},
  1:{"Example1": "Example1"},
  2:{"Example1": "Example1"}
};

const obj2 = {
  0:{"Example2": "Example2"},
  1:{"Example2": "Example2"},
  2:{"Example2": "Example2"}
}
  
const result = Object.fromEntries(
                 Object.values(obj1)  // get the values of the first object
                   .concat(Object.values(obj2))  // get the values of the second object and add them to the values of the first
                   .map((value, index) => [ index, value ])  // re-index them
                   // or if you need actual copies of the "inner" objects
                   /*
                   .map((value, index) => [
                     index,
                     Object.assign({}, value)
                   ])
                   */
               );
  
console.log(result);

Is this "more elegant". Maybe...

Because you have key-value maps and not arrays, you can't just combine the objects. Your only way would be to iterate through all the keys and add them to the final result.

E.g. something along the lines:

const obj1 = {
  0:{"Example1": "Example1"},
  1:{"Example1": "Example1"},
  2:{"Example1": "Example1"}
};

const obj2 = {
  0:{"Example2": "Example2"},
  1:{"Example2": "Example2"},
  2:{"Example2": "Example2"}
};

function merge(...args) {
  return Object.fromEntries(                      // Create entries
     args                                         // From all arguments
     .flatMap(o => Object.values(o))              // Get values (discard keys)
     .map((element, index) => [ index, element ]) // Remap them
  );
}

console.log(merge(obj1, obj2));

// Will output
// {
//  0: { Example1: "Example1" },
//  1: { Example1: "Example1" },
//  2: { Example1: "Example1" },
//  3: { Example2: "Example2" },
//  4: { Example2: "Example2" },
//  5: { Example2: "Example2" }
// }

The objects in your code are key-value pairs rather than a simple list (array).

From the looks of it there are only two possible scenarios:

  1. Your objects have a meaningful, unique key associated to them (for example, this very question on stackoverflow has key 69316153 – look at the URL bar). In this case, you really can't merge the two as they have conflicting keys. Think if there was another question on this website with the same ID as this one!
  2. The keys are not meaningful and you're happy with the same object being re-assigned a different key. In this case the correct data structure to use is arrays (obj1 = [{"Example": "..."}, {"Example": "..."}]).

If the latter is your situation, this code will work:

const obj3 = Object.values(obj1).concat(Object.values(obj2))

Object.values(obj) returns an array of values, discarding all of the keys.

Let's say we have:

 const obj1 = {
    1: { Name: "Apple" },
    2: { Name: "Watermelon" },
 };

 const obj2 = {
    2: { Name: "Pear" },
    5: { Name: "Tomato" }
 };

Object.values(obj1) will return [{ Name: "Apple" }, { Name: "Watermelon" }], while Object.values(obj2) will return [{ Name: "Pear" }, { Name: "Tomato" }].

With const obj3 = Object.values(obj1).concat(Object.values(obj2)) you will end up with:

obj3 = [
    { Name: "Apple" },
    { Name: "Watermelon" },
    { Name: "Pear" },
    { Name: "Tomato" }
];
Related