Mohan Singh
Mohan Singh

Reputation: 11

Combining two objects by keys whose values are arrays

I have two javascript objects like below

first =  {b : ["A" , "B"] , c : ["C" , "D"] , d : ["Z"]}
second = {b : ["E" , "F"] , c : ["X"]}

I want result like this

result = {b : ["A" , "B" , "E" , "F"] , c : ["C" , "D" ,"X"] , d :["Z"]}

I was playing around npm lodash but could not find a way to do it. Can some body help. I am new to Javascript world.

Upvotes: 0

Views: 63

Answers (5)

alebianco
alebianco

Reputation: 2555

With no third party library needed (lodash or else) and a nice functional style, you can do it like this

let first =  {b : ["A" , "B"] , c : ["C" , "D"] , d : ["Z"]}
let second = {b : ["E" , "F"] , c : ["X"]}
let sources = [first, second];

let unique = (...sources) => Array.from(new Set([].concat(...sources)));
let join = (...sources) => key => [].concat(...sources.map(source => source[key] || []));

let keys = unique(...sources.map(source => Object.keys(source)));

let merged = keys.reduce((map, key) => (map[key] = join(first, second)(key)) && map, {});

console.log(merged);

this will handle any number of dictionaries as a source and merge all of them together.

Upvotes: 0

Rhumborl
Rhumborl

Reputation: 16609

The lodash mergeWith docs use this exact thing as an example:

function customizer(objValue, srcValue) {
  // if merging 2 arrays, concat them together
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
}

var first =  {b : ["A" , "B"] , c : ["C" , "D"] , d : ["Z"]},
second = {b : ["E" , "F"] , c : ["X"]}
console.log(_.mergeWith(first, second, customizer));
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js"></script>

Upvotes: 0

Shilly
Shilly

Reputation: 8589

var first = {b : ["A" , "B"] , c : ["C" , "D"] , d : ["Z"]};
var second = {b : ["E" , "F"] , c : ["X"]};
// merge expects an array of objects to be used as its parameter
var merge = function merge( objs ) {
    var result = {};
    // for each object sent to this function.
    objs.forEach(function( obj ) {
        // Grab the array containing all the property keys.
        var keys = Object.keys(obj);
        // Loop over each keyname
        keys.forEach(function( keyName ) {
            // first, check if the key exists in our result. If not, create it and assign it an array.
            if (!result.hasOwnProperty(keyName)) result[keyName] = [];
            // Merge the array inside the object into the result by concatenation.
            result[keyName] = result[keyName].concat(obj[keyName]);
        });
    });
    return result;
};
// Use the function
var result = merge([ first, second ]);
console.log(JSON.stringify(result));
// The caveat here is that all the letters in the array are just added, we don't check for duplicates atm
// If duplicates are a thing, just change the .concat into another loop that checks if a letter is already in the array or not.

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122047

You could use mergeWith() and add custom function to concat arrays as customizer argument.

var first =  {b : ["A" , "B"] , c : ["C" , "D"] , d : ["Z"]}
var second = {b : ["E" , "F"] , c : ["X"]}

var result = _.mergeWith(first, second, function(a, b) {
  return [].concat(a, b)
})
console.log(JSON.stringify(result))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

Upvotes: 3

Shubham
Shubham

Reputation: 1793

This will help you.

var first =  {b : ["A" , "B"] , c : ["C" , "D"] , d : ["Z"]};
var second = {b : ["E" , "F"] , c : ["X"]};

var newObj = {};

for(let i in first) {
  if(second.hasOwnProperty(i)) {
    var tempArray = first[i];
    
    for(let j in second[i]) {
      tempArray.push(second[i][j]);
    }
    
    newObj[i] = tempArray;
    
  } else {
    newObj[i] = first[i];
  }
}


console.log(JSON.stringify(newObj));

Upvotes: 0

Related Questions