简体   繁体   中英

How do I build an object counting occurrences in an Array in JavaScript?

I want to count how often a number in an Array occurs. For example, in Python I can use Collections.Counter to create a dictionary of how frequently an item occurs in a list.

This is as far as I've gotten in JavaScript:

var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
 /* obj[array[i]] = +=1 */ <= pseudo code
}

How can I create this frequency counter object?

You were almost there. See below code:

 var array = [1,4,4,5,5,7]; var obj = {}; for (var i=0; i < array.length; i++) { obj[array[i]] = (obj[array[i]] || 0 ) +1; } console.log(obj); 

Create an object and check if that specific key exist.If exist then increase it's value by 1

 var array = [1, 4, 4, 5, 5, 7]; var obj = {}; for (var i = 0; i < array.length; i++) { if (obj.hasOwnProperty(array[i])) { obj[array[i]] += 1; } else { obj[array[i]] = 1; } } console.log(obj) 

Close but you can't increment undefined so you need to set initial value if it doesn't exist

var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
  obj[array[i]] = (obj[array[i]] || 0) +1 ;
}

You can use the ? : ? : ternary operator to set initial value as 1 and then increment it on subsequent matches.

 var array = [1,4,4,5,5,7]; var obj = {}; for (var i=0; i < array.length; i++) { obj[array[i]] = obj[array[i]]?obj[array[i]]+1:1; } console.log(obj); 

If the array is always going to be same, and you are going to check frequency of multiple items in the same array without it it being modified, @JohanP's answer is good.

But if you are only going to check frequency of only one item, or the array can change, creating the object is nothing but extra overhead.

In that case, you can do something like this:

 const getItemFrequency = function(array, item) { return array.filter(i => i === item).length; } var array = [1,4,4,5,5,7]; console.log(getItemFrequency(array, 4)); 

Concise logic written as proper function:

function countArrayItemFrequecy(array) {
  const length = array.length;
  const map = {};
  for ( let i = 0; i < length; i++ ) {
    let currentItem = array[i];
    if (typeof map[currentItem] !== 'undefined' ) {
      map[currentItem]++
    } else {
      map[currentItem] = 1
    }
  }
  return map;
}

You need to make sure to assign default value to your frequency object for the first occurrence of the item. As a shortcut you can use ternary operator

var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
 obj[array[i]] = obj[array[i]] ? obj[array[i]]++ : 1;
} 

which is the same as:

var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
 if (obj[array[i]]) {
     obj[array[i]]++;
 } else {
   obj[array[i]] = 1;
 }
} 

You can use Object.assign : below clones map and then increments/adds the counter. These are pure (no side effects/param reassignment), single-purpose functions.

addToMap does the same thing as { ...map, map[e]: [e]: (map[e] || 0) + 1 } , but that requires babel.

const addToMap = (map, e) => Object.assign({}, map, { [e]: (map[e] || 0) + 1 });
const buildMap = a => a.reduce(addToMap, {});

Using Array.reduce :

arr.reduce(function (acc, item) {
  acc[item] = (acc[item] || 0) + 1;
  return acc;
}, {});

Example:

 var arr = [1,1,2,4,1,4]; var counts = arr.reduce(function (acc, item) { acc[item] = (acc[item] || 0) + 1; return acc; }, {}); console.log(counts);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM