2

I am looking for a concise JavaScript function which takes some values and returns the unique values sorted by the number of occurrences, the most frequent first.

For example, if the input is the array [3,2,2,2,2,1,2,1] then the output should be [2,1,3].

3
  • 3
    After you're done looking, start implementing :) Commented Feb 14, 2012 at 16:21
  • What other collections do you mean? There are only objects ({}) and arrays ([]), and I'm not sure how you'd apply this to objects. Commented Feb 14, 2012 at 16:23
  • Your probably right, I didn't think so much about that, I have removed that stuff from the original question. Commented Feb 14, 2012 at 16:29

2 Answers 2

17

Here's my first stab. I bet we can make it simpler, but this seems okay.

 function fancyUnique(arr) {

   var counts = {}; // store counts for each value
   var fancy = []; // put final results in this array
   var count = 0; // initialize count

   // create counts object to store counts for each value of arr
   for (var i = 0; i < arr.length; i++) {
     count = counts[arr[i]] || 0;  // use existing count or start at 0
     count++; // increment count
     counts[arr[i]] = count; // update counts object with latest count
   }

   // take all keys from counts object and add to array
   // also: object keys are string, so must parseInt()
   for (var key in counts) {
     fancy.push(parseInt(key, 10)); 
   }

   // sort results array in highest to lowest order
   return fancy.sort(function(a, b) { 
     return counts[b] - counts[a]; 
   })
 }


fancyUnique([22,22,1,1,1,1]) // [ 1, 22 ]
Sign up to request clarification or add additional context in comments.

5 Comments

I like it. I can't see any way to improve it actually. Did you just write that from scratch or is it from your lib? :)
It's a little cryptic, e.g. what happens in the count = uniques[arr[i]] || 0; line, could you add a few comments please
I will add a comment. It just says basically if there is no count yet for a specific value then initialize it at 0.
Mm... stacksort took this: [[5,8,4,9], [12,32,6,5,8], [4,2]] and turned it into this: [5,12,4] using this answer. Little bit odd.
Fails on the array [1, 2, 3, 4, 1, 4, 32, 1, 3, 1, 1.0004, 5.03274, 2.93456e27, 2.93456e27, 2.93456e39, 0, 1], output should be [1, 3, 4, 2.93456e27, 2, 3, 32, 1.0004, 5.03274, 2.93456e39, 0] but instead was [1,1,3,4,0,2,32,5,2,2].
0
var data=[3,2,2,2,2,1,2,1];
console.log(countUnique(data));

function countUnique(data){
  var count={};
  $(data).each(function(index){                      
       count[data[index]] = count[data[index]]+1 || 1;             
  });
  return count;
}

output= "Object {1: 2, 2: 5, 3: 1}"

This works for strings as well.

Reading the output can be done using the following loop

   for(var key in count)
    {
             console.log(key); // prints the index of the array
             console.log(count[key]); //prints the number of occurrences  

    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.