fede_rosario
fede_rosario

Reputation: 105

Array group by twice and count occurrences

I have the following array:

var array = [
  { idOne: 1, oneText: 'one', idTwo: 2, twoText: 'two' },
  { idOne: 1, oneText: 'one', idTwo: 2, twoText: 'two' },
  { idOne: 12, oneText: 'twelve', idTwo: 23, twoText: 'twentythree' },
  { idOne: 12, oneText: 'twelve', idTwo: 23, twoText: 'twentythree' },
  { idOne: 12, oneText: 'twelve', idTwo: 25, twoText: 'twentyfive' },
  { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' },
  { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' },
  { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' },
  { idOne: 16, oneText: 'sixteen', idTwo: 50, twoText: 'fifty' },
  { idOne: 16, oneText: 'sixteen', idTwo: 50, twoText: 'fifty' },
  { idOne: 18, oneText: 'eighteen', idTwo: 90, twoText: 'ninety' }
];

I'm trying to group them first by idOne, then by idTwo, and count how many of them are found, and then sort them:

I currently have the following method:

var result = _.chain(array)
    .groupBy("idOne")
    .map(function(idOne, idOneKey) {
        return _.chain(idOne)
            .groupBy("idTwo")
            .map(function(idTwo, idTwoKey) {
                return {                
                    id: idOneKey + '-' + idTwoKey
                }
            })
            .value();
    })
    .value();

But I want to return the following array or object, not sure which one would be best:

result = {
  'one-two': 2,
  'twelve-twentythree': 2,
  'twelve-twentyfive': 1,
  'sixteen-fiftysix': 3
  ...
}

It does not have to be with underscore or lodash, just whatever it works.

Upvotes: 0

Views: 986

Answers (3)

Gruff Bunny
Gruff Bunny

Reputation: 27976

You could use countBy instead of groupBy:

let result = _.countBy(array, item => item.oneText + '-' + item.twoText);

Upvotes: 2

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

Ecamscript5 alternative solution (based on Array.reduce() function):

var arr = [
  { idOne: 1, oneText: 'one', idTwo: 2, twoText: 'two' }, { idOne: 1, oneText: 'one', idTwo: 2, twoText: 'two' }, 
  { idOne: 12, oneText: 'twelve', idTwo: 23, twoText: 'twentythree' }, { idOne: 12, oneText: 'twelve', idTwo: 23, twoText: 'twentythree' },
  { idOne: 12, oneText: 'twelve', idTwo: 25, twoText: 'twentyfive' }, { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' },
  { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' }, { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' },
  { idOne: 16, oneText: 'sixteen', idTwo: 50, twoText: 'fifty' }, { idOne: 16, oneText: 'sixteen', idTwo: 50, twoText: 'fifty' },
  { idOne: 18, oneText: 'eighteen', idTwo: 90, twoText: 'ninety' }
],
result = arr.reduce(function(r, o){
    var k = o.oneText +'-'+ o.twoText;
    r[k] = (r[k])? (r[k]+1) : 1;
    return r;
}, {});

console.log(result);

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386654

You could use an array for the keys to group on for the hash table to count.

var array = [{ idOne: 1, oneText: 'one', idTwo: 2, twoText: 'two' }, { idOne: 1, oneText: 'one', idTwo: 2, twoText: 'two' }, { idOne: 12, oneText: 'twelve', idTwo: 23, twoText: 'twentythree' }, { idOne: 12, oneText: 'twelve', idTwo: 23, twoText: 'twentythree' }, { idOne: 12, oneText: 'twelve', idTwo: 25, twoText: 'twentyfive' }, { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' }, { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' }, { idOne: 16, oneText: 'sixteen', idTwo: 56, twoText: 'fiftysix' }, { idOne: 16, oneText: 'sixteen', idTwo: 50, twoText: 'fifty' }, { idOne: 16, oneText: 'sixteen', idTwo: 50, twoText: 'fifty' }, { idOne: 18, oneText: 'eighteen', idTwo: 90, twoText: 'ninety' }],
    result = {};

array.forEach(function (o) {
    var key = ['oneText', 'twoText'].map(k => o[k]).join('-');
    result[key] = (result[key] || 0) + 1;
});

console.log(result);

Upvotes: 1

Related Questions