3

I have an array of n number of items

var arr1 = [2, 0, 0, 1, 1, 2, 0, 0, 0, 2, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2, 1, 2, 2, 0, 1, 2, 2, 1, 1, 0, 1, 1, 0, 2, 1, 0, 0, 0, 2, 1, 1, 1, 2, 2, 1, 0, 0, 0, 2, 2, 2, 2, 2, 1, 0, 2, 2, 0, 2, 2, 0, 2, 0, 0, 1, 2, 1, 0, 2, 1, 0, 1, 2, 0, 2, 0, 0, 0, 1, 2, 1, 0, 2, 0, 0, 0, 1, 2, 1, 1, 1, 1]

as you see the array only has i different values (v) (0,1,2),i = 3 in that case

What I would like is ending up with an array like this one.

var arr2 = [23, 45, 64]

the length of the arr2 array should corresponds to i and the values sould be the occurences of each value(v)

I am doing all kinds of loops and conditionals, but looking for a straight solution. my part so far http://jsfiddle.net/fiddlebjoern/aSsjy/2/

jQuery and/or underscore may be involved.

j0k
  • 22,600
  • 28
  • 79
  • 90
Björn
  • 12,587
  • 12
  • 51
  • 70
  • see also http://stackoverflow.com/questions/5667888/counting-occurences-of-javascript-array-elements – georg Mar 08 '12 at 12:19

4 Answers4

8

Easy peasy! The values of your input become the keys of your output; you accumulate on those keys as you encounter the values:

var arr1 = [0,0,0,1,2,3,4,3,2,3,4,3,4,3,5];
var arr2 = [];

for (var i = 0; i < arr1.length; i++) {
   var n = arr1[i];
   if (arr2[n] != undefined)
       arr2[n]++;
   else
       arr2[n] = 1;
}

console.log(arr2);  // Output: [3, 1, 2, 5, 3, 1]

Live demo.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Close, but no cigar. The members of the array must be initialised as numbers (zero would be best). What you have returns `[,NaN,NaN,NaN,NaN,NaN]`. – RobG Mar 08 '12 at 11:35
  • @RobG: I did. And, no, it doesn't. Did you click on the link labelled "demo"? Or even read the code? – Lightness Races in Orbit Mar 08 '12 at 11:36
  • No, I pasted your original posted code into a browser. You've changed it so it works. – RobG Mar 08 '12 at 11:52
  • really good ... i didnt mention it, but there could also be a string in the initial array. – Björn Mar 08 '12 at 11:53
  • @RobG: About 15 seconds after posting, yes. That was 16 minutes before your comment. – Lightness Races in Orbit Mar 08 '12 at 11:53
  • @Marcel: That completely changes things. Be more precise next time please. You will have to use an object rather than an array, then; fortunately you can probably just swap `var arr2 = []` for `var obj2 = {}` and be done with it. – Lightness Races in Orbit Mar 08 '12 at 11:54
  • 16 Minutes? I see only ~5 minute difference, giving you just enough time to edit your answer without it being shown to be edited. Must have made it by the skin of your teeth. :-) – RobG Mar 08 '12 at 11:58
  • Oh yes, I can't see where I got the 16 minute figure now. Still, you must not have been refreshing this page particularly often; as I said, the edit occurred _very_ quickly. – Lightness Races in Orbit Mar 08 '12 at 13:00
5

Sounds like a job for "reduce"

arr2 = arr1.reduce(function(a, v) {
    a[v] = (a[v] || 0) + 1;
    return a;
}, [])

Also, your arr2 is actually associative, so it's better to use an object instead:

map = arr1.reduce(function(a, v) {
    a[v] = (a[v] || 0) + 1;
    return a;
}, {})

reduce is Javascript 1.8, for older browsers you need an emulation or use a library like underscore.js.

Example with underscore.js:

arr2 = _(arr1).chain().groupBy(_.identity).map(_.size).value()

This is perhaps not so "easy" as other answers, but at least you can learn something from this.

For the sake of being complete, here's the correct way to use a plain loop for the same task:

counter = [] // or {}
for (var i = 0; i < arr.length; i++)
     counter[arr[i]] = (counter[arr[i]] || 0) + 1;
georg
  • 211,518
  • 52
  • 313
  • 390
  • His code explicitly states he wants an array, not a normal object. – Lightness Races in Orbit Mar 08 '12 at 11:35
  • @LightnessRacesinOrbit—which is likely why an answer with an array was given first, but an object suggested as a possibly more suitable option. – RobG Mar 08 '12 at 11:56
  • @RobG: It's given as part of a logical inference ("so") predicated on "your `arr2` is actually associative", which makes little sense when an explicit requirement was that it should no longer be. Still, apparently the question has since changed. – Lightness Races in Orbit Mar 08 '12 at 13:01
2

Based on the other answer, here's one that works:

var arr1 = [1,2,3,4,3,2,3,4,3,4,3,5];
var arr2 = [];
var n, m;

for (var i=0, iLen=arr1.length; i < iLen; i++) {
  n = arr1[i];
  m = arr2[n];
  arr2[n] = m? ++m : 1;
}

alert(arr2)
RobG
  • 142,382
  • 31
  • 172
  • 209
1

You can use array_count_values:

<?php
     $array = array(1, "hello", 1, "world", "hello");
     print_r(array_count_values($array));
?>

The output is:

Array
(
    [1] => 2
    [hello] => 2
    [world] => 1
)
botzko
  • 630
  • 3
  • 8