Is there a Javascript function similar to the Python Counter function?
I am attempting to change a program of mine from Python to Javascript and I was wondering if there was a JS function like the Counter function from the collections module in Python.
Syntax for Counter
from collection import Counter
list = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a']
counter = Counter(list)
print counter
output
Counter({'a':5, 'b':3, 'c':2})
DIY JavaScript solution:
var list = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a'];
function Counter(array) {
var count = {};
array.forEach(val => count[val] = (count[val] || 0) + 1);
return count;
}
console.log(Counter(list));
Update:
Alternative that uses a constructor function:
var list = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a'];
function Counter(array) {
array.forEach(val => this[val] = (this[val] || 0) + 1);
}
console.log(new Counter(list));
You can use Lo-Dash’s countBy function:
var list = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a'];
console.log(_.countBy(list));
I know I’m late but in case if someone is looking at this in 2020 you can do it using reduce, for example:
const counter = (list) => {
return list.reduce(
(prev, curr) => ({
...prev,
[curr]: 1 + (prev[curr] || 0),
}),
{}
);
};
console.log(counter([1, 2, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 1, 0]));
// output -> { '0': 1, '1': 6, '2': 2, '3': 1, '4': 1, '5': 1, '6': 1, '7': 1 }
more advance example with a callback function and context binding
const data = [1, 2, 3, 4, 5];
const counter = (list, fun, context) => {
fun = context ? fun.bind(context) : fun;
return list.reduce((prev, curr) => {
const key = fun(curr);
return {
...prev,
[key]: 1 + (prev[key] || 0),
};
}, {});
};
console.log(counter(data, (num) => (num % 2 == 0 ? 'even' : 'odd')));
// output -> { odd: 3, even: 2 }
There is also pycollections.js, which works on Node and in client-side JS.
Example:
var collections = require('pycollections');
var counter = new collections.Counter([true, true, 'true', 1, 1, 1]);
counter.mostCommon(); // logs [[1, 3], [true, 2], ['true', 1]]
For those who want a pure JavaScript solution:
function countBy (data, keyGetter) {
var keyResolver = {
'function': function (d) { return keyGetter(d); },
'string': function(d) { return d[keyGetter]; },
'undefined': function (d) { return d; }
};
var result = {};
data.forEach(function (d) {
var keyGetterType = typeof keyGetter;
var key = keyResolver[keyGetterType](d);
if (result.hasOwnProperty(key)) {
result[key] += 1;
} else {
result[key] = 1;
}
});
return result;
}
Therefore:
list1 = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a'];
console.log(countBy(list1)); // {'a':5, 'b':3, 'c':2}
list2 = ['abc', 'aa', 'b3', 'abcd', 'cd'];
console.log(countBy(list2, 'length')); // {2: 3, 3: 1, 4: 1}
list3 = [1.2, 7.8, 1.9];
console.log(countBy(list3, Math.floor)); // {1: 2, 7: 1}
In Python, the Counter
also has add
and update
methods, which are used quite commonly. So a better solution would be this:
function Counter(array) {
this.add = (val) => {
this[val] = (this[val] || 0) + 1;
};
this.update = (array) => {
array.forEach((val) => this.add(val));
};
this.update(array);
}
// Example usage
let myCounter = new Counter([1, 2, 2])
myCounter.update([3, 3, 3])
myCounter.add(4)
console.log(myCounter)
This is my solution with explicit function calls
let list = [4, 6, 5, 3, 3, 1];
function counter(list) {
let count = function(n) {
let cnt = 0;
for (let v of list) {
if (v === n) cnt++
}
return cnt
}
let [...listSet] = new Set(list);
let cntr = {};
for (let v of listSet) {
cntr[v] = count(v)
}
return cntr
}
console.log(counter(list))
Another version ->
s = "naman";
const counter = (s, sMap = {}) => {
[...s].map((el) => {
sMap[el] = sMap[el] ? sMap[el] + 1 : 1;
});
return sMap;
};
const res = counter(s);
console.log(`res`, res);
How about this pure functional way:
let list = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a'];
function counter(array) {
return array.reduce((acc, value, index) => {
acc[value] = value in acc ? acc[value] + 1: 1
return acc;
}, {});
}