2

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?

5
  • 2
    Why are these objects in the first place? They should be arrays. Commented Sep 24, 2021 at 13:55
  • @Andreas, this objects are approximations of real objects, that i am working with, and they are roughly in this kind of composition. Commented Sep 24, 2021 at 13:56
  • Don't add tags ("... [JS]") in the title -> What are tags, and how should I use them? Commented Sep 24, 2021 at 13:57
  • Doesn't answer the question. They should be arrays. And then it would be a simple .concat() Commented Sep 24, 2021 at 13:57
  • 1
    You should add actual examples of your input data as a minimal reproducible example, and expected output. Commented Sep 24, 2021 at 13:58

3 Answers 3

2

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...

Sign up to request clarification or add additional context in comments.

1 Comment

You could replace .fromEntries() and .map() with one .reduce() but I like that slightly more expressive version.
1

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" }
];

Comments

1

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" }
// }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.