3

I want to merge two arrays of objects. The keys are the same but the values might not always be the same.

Any solution is appreciated preferably in javascript, but a python solution is fine as well.

Here is the sample data:

var g= [ 
    { id: 36, name: 'AAA', goal: 'yes' , 'random':27},
    { id: 40, name: 'BBB', goal: 'yes' },
    { id: 39, name: 'JJJ', goal: 'yes' },
    { id: 27, name: 'CCC', goal: 'yes' , lag: "23.3343"}];


var c= [ 
    { id: 36, name: 'AAA', goal: 'yes', color:"purple" },
    { id: 40, name: 'BBB', circle: 'yes', color:"purple" },
    { id: 100, name: 'JJJ', circle: 'yes'} ];

My expected output should be :

 var finalData = [{
 { id: 36, name: 'AAA', goal: 'yes' ,'random':27, color:"purple"},
 { id: 40, name: 'BBB', circle: 'yes', color:"purple"},
 { id: 39, name: 'JJJ', goal: 'yes' },
 { id: 27, name: 'CCC', goal: 'yes' ,lag: "23.3343"},
 { id: 100, name: 'JJJ', circle: 'yes' }

  }]

Here is my current code, it works to some degree but it doesn't add keys it might have missed.

var finalData = [];
for(var i in g){
   var shared = false;
   for (var j in c)
       if (c[j].name == g[i].name) {
           shared = true;
           break;
       }
   if(!shared) finalData.push(g[i])
}
finalData = finalData.concat(c); 

finalData
2
  • What is there both has the same key say goal? Commented Dec 8, 2017 at 11:45
  • Possible duplicate of Merge 2 arrays of objects Commented Dec 8, 2017 at 11:48

3 Answers 3

4

You could use a Map for keeping same id in the same object and Object.assign for creating independent objects.

var g = [{ id: 36, name: 'AAA', goal: 'yes', 'random': 27 }, { id: 40, name: 'BBB', goal: 'yes' }, { id: 39, name: 'JJJ', goal: 'yes' }, { id: 27, name: 'CCC', goal: 'yes', lag: "23.3343" }],
    c = [{ id: 36, name: 'AAA', goal: 'yes', color: "purple" }, { id: 40, name: 'BBB', circle: 'yes', color: "purple" }, { id: 100, name: 'JJJ', circle: 'yes' }],
    map = new Map,
    result = g.concat(c).reduce(function (r, o) {
        var temp;
        if (map.has(o.id)) {
            Object.assign(map.get(o.id), o);
        } else {
            temp = Object.assign({}, o);
            map.set(temp.id, temp);
            r.push(temp);
        }
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Version without reduce and without concat.

function merge(o) {
    var temp;
    if (map.has(o.id)) {
        Object.assign(map.get(o.id), o);
        return;
    }
    temp = Object.assign({}, o);
    map.set(temp.id, temp);
    result.push(temp);
}

var g = [{ id: 36, name: 'AAA', goal: 'yes', 'random': 27 }, { id: 40, name: 'BBB', goal: 'yes' }, { id: 39, name: 'JJJ', goal: 'yes' }, { id: 27, name: 'CCC', goal: 'yes', lag: "23.3343" }],
    c = [{ id: 36, name: 'AAA', goal: 'yes', color: "purple" }, { id: 40, name: 'BBB', circle: 'yes', color: "purple" }, { id: 100, name: 'JJJ', circle: 'yes' }],
    map = new Map,
    result = [];

[g, c].forEach(function (a) {
    a.forEach(merge);
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

With dynamic key.

function mergeBy(key, data) {
    return Array.from(data
        .reduce((m, o) => m.set(o[key], { ...m.get(o[key]), ...o }), new Map)
        .values()
    );
}

var g = [{ id: 36, name: 'AAA', goal: 'yes', 'random': 27 }, { id: 40, name: 'BBB', goal: 'yes' }, { id: 39, name: 'JJJ', goal: 'yes' }, { id: 27, name: 'CCC', goal: 'yes', lag: "23.3343" }],
    c = [{ id: 36, name: 'AAA', goal: 'yes', color: "purple" }, { id: 40, name: 'BBB', circle: 'yes', color: "purple" }, { id: 100, name: 'JJJ', circle: 'yes' }],
    result = mergeBy('id', [...g, ...c]);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

14 Comments

Can you explain what r.push(temp) does because r is not an array. Also when I tried this solution with a bigger data set it only returns only the last object instead of all of the objects it looped through. I am thinking its because reduce only returns a single value. I switched reduce with a map and it didn't work either .
r is the accumulartor from reduce callback. it has as initial value an empty array.
when I tried this solution with a bigger data set it only returns only the last object instead of all of the objects it looped through. I am thinking its because reduce only returns a single value. I switched reduce with a map and it didn't work either
it is always returning all objects which are consolidated. version 2 works without reduce now.
please see third approach.
|
1

Here's a Python solution. This modifies g, which you may or may not want.

c_by_id = {d['id']: d for d in c}
for item in g:
    item.update(c_by_id.get(item['id']), {})

1 Comment

I think OP wants a JavaScript solution, since his attempt shows so.
0

This can be easily achieved by underscore functions _.uniq and _.union.

Just use this:

var finalData = _.uniq(_.union(c, g),  function (ele)  {
                    return ele.id
                })

This will return you what you are looking for.

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.