Combine multiple arrays by same key [duplicate]

2019-08-22 10:25发布

This question already has an answer here:

I'm trying combine multiple arrays by a specific key property. For example, I have

arr1

  [{
    key: 'A',
    items: [{name: 'a item'}]
  }, {
    key: 'B',
    items: [{name: 'b item'}]
  }]

arr2

  [{
    key: 'B',
    items: [{name: 'another b item'}, {name: 'more b items'}, {name: 'even more b items'}]
  }]

How do I produce the following arr3?

  [{
    key: 'A',
    items: [{name: 'a item'}]
  },
  {
    key: 'B',
    items: [{name: 'b item'}, {name: 'another b item'}, {name: 'more b items'}, {name: 'even more b items'}]
  }]

3条回答
走好不送
2楼-- · 2019-08-22 11:07

May use a hash table like this:

arr1=[{
    key: 'A',
    items: [{name: 'a item'}]
  }, {
    key: 'B',
    items: [{name: 'b item'}]
  }];

arr2=[{
    key: 'B',
    items: [{name: 'another b item'}, {name: 'more b items'}, {name: 'even more b items'}]
  }];
  
console.log(arr1.concat(arr2).reduce((function(hash){
   return function(array,obj){
    if(!hash[obj.key])
     array.push(hash[obj.key]=obj);
    else
       hash[obj.key].items.push(...obj.items);
    return array;
   };    

})({}),[]));

Some explanation:

arr1.concat(arr2)//just work with one array as its easier
.reduce(...,[]));//reduce this array to the resulting array
//through
(function(hash){//an IIFE to closure our hash object
...
})({})
//which evaluates to
  function(array,obj){//take the resulting array and one object of the input
    if(!hash[obj.key])//if we dont have the key yet
     array.push(hash[obj.key]=obj);//init the object and add to our result
    else
       hash[obj.key].items.push(...obj.items);//simply concat the items
    return array;
  };    
查看更多
地球回转人心会变
3楼-- · 2019-08-22 11:11

var arr1 = [{
    key: 'A',
    items: [{name: 'a item'}]
  }, {
    key: 'B',
    items: [{name: 'b item'}]
  }]
var arr2 =  [{
    key: 'B',
    items: [{name: 'another b item'}, {name: 'more b items'}, {name: 'even more b items'}]
  }]
  
  
var arr3 = _.map(_.groupBy(arr1.concat(arr2), 'key'), 
  val => ({
    key : val[0].key, items: _.union.apply(this,val.map(v => v.items))
    })
)
console.log(arr3)
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

查看更多
地球回转人心会变
4楼-- · 2019-08-22 11:18

Snippet I have that I've used many times for similar. Changed naming for your usecase.

var output = array.reduce(function(o, cur) {

  // Get the index of the key-value pair.
  var occurs = o.reduce(function(k, item, i) {
    return (item.key === cur.key) ? i : k;
  }, -1);

  // If the name is found,
  if (occurs >= 0) {

    // append the current value to its list of values.
    o[occurs].item = o[occurs].value.concat(cur.items);

  // Otherwise,
  } else {

    // add the current item to o (but make sure the value is an array).
    var obj = {key: cur.key, item: [cur.items]};
    o = o.concat([obj]);
  }

  return o;
}, []);
查看更多
登录 后发表回答