Search code examples
lodash

Using Lodash to GroupBy a specific value in another object


Using Lodash 4.17.11, how do you use groupBy to group by value? Let me explain:

An array of objects:

{
  a: 88,
  b: 11,
},
{
  a: 99,
  b: 88
},
{
  a: 22,
  b: 10
}

Expected result:

88: [{
  a: 88,
  b: 11
},
{
  a: 99,
  b: 88
}]

Doing the below would be based on the actual key

._groupBy(array, (arr) => arr.a)

But I need to group by the actual value. Am I making sense? If b is the same as a in another object, then group it.

Im working with an old code base where things are not structured. Thanks.


Solution

  • You could do this in relatively concise manner with ES6 and Array.reduce:

    const group = arr => arr.reduce((r,{a,b}) => {
      if(!r[a] && !r[b]) r[a] = r[b] = {a,b}
      else {
       if(r[a]) r.grp[a] = [...r.grp[a] || [r[a]], {a,b}]
       if(r[b]) r.grp[b] = [...r.grp[b] || [r[b]], {a,b}]
      }
      return r
    }, {grp: {}}).grp
    
    console.log(group([{ a: 88, b: 11, }, { a: 99, b: 88 }, { a: 22, b: 10 }]))
    console.log(group([{ a: 88, b: 11, }, { a: 99, b: 88 }, { a: 22, b: 10 }, { a: 22, b: 88 }]))

    I would also argue that this should be considerably faster than doing 1 groupBy on 'a', then another on 'b' and then yet another loop to _.mergeBy as with lodash.

    But if you want lodash you could do something like this:

    const group = arr => {
      return _.pickBy(
        _.mergeWith(
          _.groupBy(arr, 'a'),
          _.groupBy(arr, 'b'),
         (ov,sv,k,o,s) => o[k] && s[k] ? o[k].concat(s[k]) : false
       ),
       x => _.isArray(x) && x.length > 1)
    }
    
    console.log(group([{ a: 88, b: 11, }, { a: 99, b: 88 }, { a: 22, b: 10 }]))
    console.log(group([{ a: 88, b: 11, }, { a: 99, b: 88 }, { a: 22, b: 10 }, { a: 22, b: 88 }]))
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

    Where you would group by each of the props then merge only those arrays where there is the same key and then since the output is in arrays just pickBy the ones that have more than 1 item in them.