Is there a Javascript function similar to the Python Counter function?

Question:

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})
Asked By: michaelpri

||

Answers:

You can use Lo-Dash’s countBy function:

var list = ['a', 'b', 'c', 'b', 'a', 'b', 'c', 'a', 'a', 'a'];
console.log(_.countBy(list));

JSFiddle example

Answered By: Sebastian S

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]] 
Answered By: Brian Weidenbaum

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}
Answered By: iulian

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));

JSFiddle example

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));

JSFiddle example

Answered By: nitsas

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 }
Answered By: rowadz

Here is a simple and easy to read solution:

 const word1 = "tangram"
    const dict1 = {}
    for (let char of word1){
     console.log(char)
     if (dict1[char]){
       dict1[char] += 1
       }else{
     dict1[char]= 1
     }
    }

enter image description here

enter image description here

Answered By: Royer Adames

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))
Answered By: EMMANUEL EZEKA

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);

Answered By: Nk03

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)

Answered By: Ulf Aslak

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;
    }, {});
}

Fiddle Link

Answered By: Laszlo
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.