Search code examples
javascriptarraysobjectecmascript-6lodash

javascript find object by same keys and merge them


So i'm have an array of objects, i've created two dictonaries to map the names. I want to find all object with the same key and merge them. Also concatenate that values. Here is what i've done, but stucked:

const wordcloudData = {
  'pretty cool': [3, 1, ['161', '329']],
  'pretty damn': [2, 1, ['111', '131']],
  'pretty nice': [1, 1, ['211', '499']],
  'great': [4, 1, ['18', '19']],
};

const dict = {
  'pretty cool': 1, 
  'pretty damn': 1,
  'pretty nice': 1,
};

const dictNames = {
  1: 'nice',
}


const formattedArray = _
  .chain(wordcloudData)
  .keys()
  .map(item => {
    const [weight, color, reviews] = wordcloudData[item];

    return {
      name: dictNames[dict[item]] || item,
      weight: weight,
      color: color,
      reviews: reviews,
    }
  })
  /* Here i'm getting that type of array:
   [ 
    { name: 'nice', weight: 1, color: 1, reviews: [ '211', '499' ] },
    { name: 'nice', weight: 2, color: 1, reviews: [ '111', '131' ] },
    { name: 'nice', weight: 3, color: 1, reviews: [ '161', '329' ] },
    { name: 'great', weight: 4, color: 1, reviews: [ '18', '19' ] } 
   ]
  */
  .groupBy('name')
  .map(_.spread(_.assign)) // Here i'm trying to get rid of objects with same key, but something goes wrong
  .value();

I think i'm doing it wrong when removing duplicates? What should i do next?

To explain what I want, will show what array I want it to be:

Initial array of object:

{
 'pretty cool': [3, 1, ['161', '329']],
 'pretty damn': [2, 1, ['111', '131']],
 'pretty nice': [1, 1, ['211', '499']],
 'great': [4, 1, ['18', '19']],
}; 

Result array of objects:

{ name: 'nice', weight: 6, color: 1, reviews: [ '161', '329', '111', '131', '211', '499'] },
{ name: 'great', weight: 4, color: 1, reviews: [ '18', '19' ] } 

Solution

  • Use _.mergeWith() and choose how to combine the values according to the key:

    const wordcloudData = {
      'pretty cool': [3, 1, ['161', '329']],
      'pretty damn': [2, 1, ['111', '131']],
      'pretty nice': [1, 1, ['211', '499']],
      'great': [4, 1, ['18', '19']],
    };
    
    const dict = {
      'pretty cool': 1, 
      'pretty damn': 1,
      'pretty nice': 1,
    };
    
    const dictNames = {
      1: 'nice',
    }
    
    const merger = _.partial(_.invoke, {
      weight: _.add,
      reviews: _.concat,
    });
    
    const formattedArray = _(wordcloudData)
      .map(([weight, color, reviews], item) => ({
        name: _.get(dictNames, dict[item], item),
        weight,
        color,
        reviews
      }))
      .groupBy('name')
      .map(v => _.mergeWith(...v, (o, s, k) => merger(k, o, s)))
      .value();
      
    console.log(formattedArray);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>