1

I am looking for a way to merge many objects with the same key to a one big object. The number of objects can be more that 2.

For example I have this code:

const a = {
  en: {
    hello: 'Hello'
  },

  fr: {
    hello: 'Bonjour'
  }
}

const b = {
  en: {
    goodbye: 'Goodbye'
  },

  fr: {
    goodbye: 'Au revoir'
  }
}

How to merge that into this:

{
  locale: 'en',
  messages: {
    en: {
      hello: 'Hello',
      goodbye: 'Goodbye'
    },

    fr: {
      hello: 'Bonjour',
      goodbye: 'Au revoir'
    }
  }
}
4
  • 1
    what qualifies locale: 'en'? Commented Sep 2, 2018 at 9:27
  • maybe a look worth: stackoverflow.com/q/52131927 Commented Sep 2, 2018 at 9:28
  • 1
    Welcome to Stack Overflow! Please take the tour (you get a badge!) and read through the help center, in particular How do I ask a good question? Your best bet here is to do your research, search for related topics on SO, and give it a go. If you get stuck and can't get unstuck after doing more research and searching, post a minimal reproducible example of your attempt and say specifically where you're stuck. People will be glad to help. Commented Sep 2, 2018 at 9:29
  • Possible duplicate of Nested object assign Javascript Commented Sep 2, 2018 at 9:51

4 Answers 4

2

You could use a deep merge function for every level of the object.

The function deepMerge works as single function for a given target or as callback for Array#reduce, where an array of objects is iterated and an empty object is supplied as startvalue for reducing.

As result, you need a new object and assign the merges objects as new property messages.

function deepMerge(target, source) {
    Object.entries(source).forEach(([key, value]) => {
        if (value && typeof value === 'object') {
            deepMerge(target[key] = target[key] || {}, value);
            return;
        }
        target[key] = value;
    });
    return target;
}

var a = { en: { hello: 'Hello' }, fr: { hello: 'Bonjour' } },
    b = { en: { goodbye: 'Goodbye' }, fr: { goodbye: 'Au revoir' } },
    c = { locale: 'en', messages: [a, b].reduce(deepMerge, {}) };
    
console.log(c);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

Comments

0

Function mergeArray for array merging

const mergeArray = (firstArray, secondArray) => {
  return {
    locale: 'en',
    messages: {
      en: {
          ...firstArray.en,
          ...secondArray.en
      },
      fr: {
        ...firstArray.fr,
        ...secondArray.fr
      }
    }
  }
};

console.log(mergeArray(a, b));

Below snippets give you expected output.

const value = { locale: 'en', messages: { en: { ...a.en, ...b.en }, fr: { ...a.fr, ...b.fr } }};
console.log(value)

1 Comment

I have implemented the same in the function.
-1

If you want it to a new object, you can use Object.Assign({}, a, b)

read this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

4 Comments

update it to be into new object, Object.Assign({}, a, b) @Attersson
And the second edit creates a new object, in contrast to OP request to merge a into the second object. No no.
@Attersson - The fact that a is a const has nothing whatsoever to do with whether you can modify the object it refers to. You can. (That doesn't make this a good answer, but thought I'd mention it.)
@T.J.Crowder You are correct, I mean it is supposedly not the target of the final merge (and therefore the non mutating one), in OP intent and the original version of this answer still had them swapped
-1

Try this when the number of objects is dynamic:

var o, k, v, n, A=[a,b], r={}
for(o in A) for(k in A[o]) if(!r[k]) r[k]={};
for(o in A) for(v in A[o]) for(n in A[o][v]) if(!r[v][n]) r[v][n]= A[o][v][n];
console.log(r);
console.log({locale: 'en',messages:r});

1 Comment

in my old answers, i supposed that the number of objects is 2. please check my updated answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.