简体   繁体   中英

Javascript merge objects to key -> set of values

I'm using underscore, and I'm wondering if there's a more efficient way of accomplishing the following - seems like this should be a function in underscore.

var obj1 = { test: 'hello' },
    obj2 = { test: 'hello2' };

var merged = {};
_.each(_.keys(obj1), function(key) { merged[key] = [obj1[key], obj2[key]]; });

console.log(merged);

Also the limitations of this are that any keys in obj2 not present in obj1 will not be counted - it would be nice if I could get something akin to a full outer join, where the value of one side or the other will be null if it doesn't exist. Also, it would be nice if this wasn't limited to two objects.

You can do this with plain JS, and multiple objects:

 var merge = function() { return [].reduce.call(arguments, function(acc, obj) { Object.keys(obj).forEach(function(k) { acc[k] = (acc[k] || []).concat(obj[k]) }) return acc }, {}) } var a = { prop: 1 } var b = { prop: 2 } var c = { prop: 3 } console.log(merge(a, b, c)) //=> {prop: [1,2,3]} 

There may be a more underscore-ish way to do it, but it's a fairly straightforward function in plain JS:

function mergeObjects() {
  var merged = {};

  for ( var i = 0; i < arguments.length; ++i )
    {
      var o = arguments[i];

      for ( var f in o )
        if (o.hasOwnProperty(f))
          {
            merged[f] = merged[f] || [];
            merged[f].push(o[f]);
          }
    }

  return merged;
}

This version accepts any number of arguments, assuming they're all objects.

Example: http://codepen.io/paulroub/pen/sDcym

I'll throw my hat in the ring here as well:

function merge(){
  var objects = arguments,
      merged = {},
      keys = _.union(_.flatten(_.map(objects, function(arg){ return _.keys(arg); })));
  _.each(keys, function(key){
      _.each(objects, function(obj){
          merged[key] = merged[key] || [];
          merged[key].push(obj.hasOwnProperty(key) ? obj[key] : null);
      });
  });
  return merged;
}

Can't speak for it's readability or speed, as I don't think it wins in either category. However, besides your own answer I think this is the only one that actually meets all of the requirements.

example: http://jsfiddle.net/z01ubsny/1/

Here's a better solution than what I provided in my original post, though I'm still not convinced it's optimal.

  var objs = [{ test: 'hello', test2: 'word', test3: 2 }, { test: 'hello2', test0: 1 }]; var merged = _.chain(_.defaults.apply(_, objs)) .keys() .map(function(k) { return [k, _.pluck(objs, k)] }) .object() .value(); console.log(merged); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM