0

Would like to merge an array of objects resulting in an object of unique keys and array of values (duplication of values is ok). Solutions in vanilla JS or lodash preferred.

eg - from this:

[{ 
  a: 1, 
  b: 2 
}, { 
  a: 1, 
  c: 3 
}]

to this:

{ 
  a: [1, 1],
  b: [2],
  c: [3]
}
3
  • 1
    @eclanrs already has an answer to that here: stackoverflow.com/questions/24336202/… Commented Jul 5, 2017 at 7:20
  • @Qiqo There input is individual objects. Here OP has array of objects. Still can be used as merge(...array). Commented Jul 5, 2017 at 7:29
  • @Tushar. thanks I've updated my answer to reflect the change in order to accept array of objects. Commented Jul 5, 2017 at 7:49

5 Answers 5

3

You can use _.mergeWith() with the spread syntax to combine the objects:

const data = [{"a":1,"b":2},{"a":1,"c":3}];

const result = _.mergeWith({}, ...data, (v1 = [], v2) => [...v1, v2]);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

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

2 Comments

If OP wanted to use external libraries, he/she would have done so. Stop obfuscating the web by loading in scripts for every little function.
Look at the tags attached to the question. They contain the word lodash.
1

ES6 variant:

const a = [{ 
  a: 1, 
  b: 2 
}, { 
  a: 1, 
  c: 3 
}]

const b = a.reduce((acc, cur) => Object.assign(acc, 
  ...Object.keys(cur).map(key => ({ [key]: (acc[key] || []).concat(cur[key]) })))
, {})

console.log(b)

Comments

0

without loadash:

  var t = [{ 
  a: 1, 
  b: 2 
}, { 
  a: 1, 
  c: 3 
}];
var result = {};
debugger;
for(var i=0; i<t.length; i++){
    for(var j in t[i]){
        if(result.hasOwnProperty(j)){
            result[j].push(t[i][j]); 
        }else{
            result[j] = [t[i][j]];
        }
    }
}
console.log(result);

Comments

0

A quick search here in stack reveals that @elclanrs already wrote code for that here However based on the comments, it needs a little tweaking to accept an array of objects, so I added a bit of change to the original code itself.

so basically it boils to the function call:

var merge = function() {
  return [].reduce.call(arguments, function(acc, x) {
  for(i=0;i<x.length;i++){
    Object.keys(x[i]).forEach(function(k) {
      acc[k] = (acc[k]||[]).concat([x[i][k]])
    });
    }
    return acc
  },{})
}
}

Here's a snippet using the function call (with a bit of small change I put) in that post:

var x = [{a: 1, b: 2}, {a: 1,c: 3}]

var merge = function() {
  return [].reduce.call(arguments, function(acc, x) {
  for(i=0;i<x.length;i++){
    Object.keys(x[i]).forEach(function(k) {
      acc[k] = (acc[k]||[]).concat([x[i][k]])
    });
    }
    return acc
  },{})
}

y = merge(x);

alert(JSON.stringify(y));

2 Comments

Oh, you added an answer. Pass array as merge(...x).
Thanks @Tushar, I've updated my answer to reflect the changes in order to accept array of objects
0

You can use lodash#mergeWith wrapped in a lodash#spread to make lodash#mergeWith treat an array as a list of arguments. We use lodash#concat as a supporting function to concatenate an empty object (to avoid mutating the objects in the collection), the collection, and the customizer function that merges the entire collection. The customizer is composed using lodash#flow, wherein its first argument is lodash#concat that only accepts an arity of 2 using lodash#ary and the second argument uses lodash#compact -- It removes all undefined values in an array.

var result = _.spread(_.mergeWith)(
  _.concat({}, data, _.flow(_.ary(_.concat, 2), _.compact))
);

var data = [{
  "a": 1,
  "b": 2
}, {
  "a": 1,
  "c": 3
}];

var result = _.spread(_.mergeWith)(
  _.concat({}, data, _.flow(_.ary(_.concat, 2), _.compact))
);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

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.