I need to iterate over a large set of records and count the number of distinct values in a particular field:
>> const cats = [
{name: 'Sophie', color: 'black'},
{name: 'Moo', color: 'grey'},
{name: 'Tipper', color: 'black'}
]
>> countBy(cats, 'color')
Map('black' => 2, 'grey' => 1) # (precise data structure unimportant)
Hey, that's what lodash countBy is for! But in my application, performance is paramount. In my (very informal) benchmark, this simple code beats lodash by around 50%:
function countBy<R extends object>(records: R[], key: keyof R) {
const counts = new Map<keyof R, number>()
for (const i = 0; i < records.length; i++) {
const value = records[i][key]
counts.set(value, (counts.get(value) || 0) + 1)
}
}
(This is perhaps unsurprising since it doesn't need to handle fancier "iteratees" than keyof R
.)
Question: is there any way to beat this algorithm, speed-wise?