3

I'm trying to build a javascript function which would count the number of occurrences of each word in an input array.

Example :

Input

a=["a","booster","booster","constructor","adam","adam","adam","adam"]

Output:

"a":1
"booster":2
"constructor":1
"adam":4

Output should be dict-alike.

I'm new to javascript and I tried to use a dict. But objects have a property called "constructor", so cnt["constructor"] seems not to work.

Here is my code and the result:

var cnt={};
console.log("constructor");

for(var i=0;i<a.length;++i)
{
    if(! (a[i] in cnt))
        cnt[a[i]]=0;
    else
        cnt[a[i]]+=1;
}

for(var item in cnt)
    console.log(item+":"+cnt[item]);

Result:

enter image description here

You can see that 1 is added to constructor of cnt as a string.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
Booster
  • 1,650
  • 13
  • 18
  • 2
    Interesting question actually. Instead of blindly downvoting, try to solve the OP problem. Is it important if he tried anything or not? – dfsq Feb 07 '14 at 11:22
  • I just don't know why this question is downvoted. It seems that array can't support the same usage as map in C++ STL because the properties. – Booster Feb 07 '14 at 11:24
  • 1
    @dfsq I agree with you, however, it's easier to understand the actual problem with some code provided. –  Feb 07 '14 at 11:50
  • @Pinal, I've edited my question and added my code. – Booster Feb 07 '14 at 12:33
  • @Andy, Question has been edited. – Booster Feb 07 '14 at 12:33
  • Ok, +1 for prevent removing this question :) – Alex Feb 07 '14 at 13:10
  • 1
    @Pinal. This question is already answered. Hope to see your answer if you have a better one. – Booster Feb 07 '14 at 13:11
  • WOW! Very odd. I'm seeing it add a constructor function too?!!? – Asher Aug 31 '15 at 22:42
  • Does this answer your question? [Counting the occurrences / frequency of array elements](https://stackoverflow.com/questions/5667888/counting-the-occurrences-frequency-of-array-elements) – Nick Oct 20 '20 at 11:36

3 Answers3

13
function count(arr){
  return arr.reduce(function(m,e){
    m[e] = (+m[e]||0)+1; return m
  },{});
}

The idea behind are

  • the use of reduce for elegance
  • the conversion of m[e] to a number using +m[e] to avoid the constructor (or toString) problem

Demonstration

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • If you log the constructor property of your result, you can find that an odd "1" is added to the constructor of the array. That's exactly where the key point is. – Booster Feb 07 '14 at 11:33
  • I've tried using array. Do you know whether javascript has map? – Booster Feb 07 '14 at 11:36
  • This code uses a map. In JavaScript we usually call map an object that is used to map properties to values. – Denys Séguret Feb 07 '14 at 11:37
  • I'd like to know why there's a downvote here. Did somebody find a bug ? – Denys Séguret Feb 07 '14 at 11:37
  • It is my downvote just now. You can see my edited question now and will find why this code is not correct. – Booster Feb 07 '14 at 11:43
  • Oh, sorry, didn't see your change maybe because of the network. This works exactly! Thank you so much! – Booster Feb 07 '14 at 11:50
  • I just edited. This makes the code much longer (1 char) and more boring but also probably much more readable. – Denys Séguret Feb 07 '14 at 11:54
  • Thank you again! By the way, you added a "+" comparing to your answer at the first time. But why does your first answer fail but this works? – Booster Feb 07 '14 at 12:00
  • 3
    @Booster because `+"constructor"` is NaN, so `(+"constructor"||0)` is `0` – Denys Séguret Feb 07 '14 at 12:01
  • Really good answer. Is this question boring or something else? Why are there some people downvoting? – Booster Feb 07 '14 at 12:08
  • @Booster Because there was no code initially and because you weren't clear at all with the problem you had encountered with "constructor". It's a good question but the way it was initially asked made it appear bad (even to me). – Denys Séguret Feb 07 '14 at 12:10
  • Oh...Really sorry for my bad description and ugly english. – Booster Feb 07 '14 at 12:11
  • 1
    @Booster Don't worry, you have 3 supporters : `+3/-8` :D –  Feb 07 '14 at 12:14
  • @wared, I don't care about reputations. However, I think this question should help a lot of beginners like me. If this question is not noticed just because of my bad description, it's a great loss. – Booster Feb 07 '14 at 12:18
  • 1
    @Booster I agree with you (the answer is pretty interesting by the way), that why I voted up. Take care to post well prepared and detailed question next time :) –  Feb 07 '14 at 12:25
  • Whether this works or not, no one understands your code. – Elise Chant Feb 22 '15 at 09:12
  • @EliseChant Obviously most coders and voters understand it. What's unclear for you ? – Denys Séguret Feb 22 '15 at 09:34
  • @dystroy with all due respect line 3 – Elise Chant Feb 22 '15 at 09:41
  • `+m[e]` is the conversion of `m[e]` to a number. If `m[e]` isn't yet defined then `+m[e]` is `NaN` and thus `+m[e]||0` is `0` (initial case) . – Denys Séguret Feb 22 '15 at 10:20
0
var arr = ['apple', 'orange', 'grape', 'apple'];
var initialValue = {};

var result = arr.reduce(function(accumulator, curr, idx, arr) {
    if (Object.hasOwnProperty.call(accumulator, curr)) {   // does current exist as key on initialValue object?
        accumulator[curr]++;
    } else {    // no key for current on initialValue object
        accumulator[curr] = 1;
    }
    return accumulator;
}, initialValue);

console.log(result);
Elise Chant
  • 5,048
  • 3
  • 29
  • 36
0

You can also create an array just by initializing [] as the initial accumulator.

var fruits = ['apple', 'orange', 'grape', 'apple'].reduce((countFruits,currentFruit)=>{
  if(typeof countFruits[currentFruit]!=="undefined"){
    countFruits[currentFruit] = countFruits[currentFruit]+1
    return countFruits
  }
  countFruits[currentFruit] = 1
  return countFruits
},[])
console.log(fruits) 
olajide
  • 972
  • 1
  • 13
  • 26