7

Using jQuery, how can I iterate over an object, and get the unique values of a key with a count of each value?

For example, for this array:

var electrons = [
    { name: 'Electron1', distance: 1 }, 
    { name: 'Electron2', distance: 1 }, 
    { name: 'Electron3', distance: 2 }, 
    { name: 'Electron4', distance: 2 }, 
    { name: 'Electron5', distance: 2 }, 
    { name: 'Electron6', distance: 2 }, 
    { name: 'Electron7', distance: 2 }, 
    { name: 'Electron8', distance: 2 }, 
    { name: 'Electron9', distance: 2 }, 
    { name: 'Electron10', distance: 2 }, 
    { name: 'Electron11', distance: 3 }, 
];

I'd like to get back the following:

var distance_counts = {1: 2, 2: 8, 3: 1};

I've got this, which works but is a bit clumsy:

var radius_counts = {};
for (var i = 0; i < electrons.length; i++) { 
    if (electrons[i].distance in radius_counts) { 
         radius_counts[electrons[i].distance] += 1;
    } else { 
         radius_counts[electrons[i].distance] = 1;
    } 
}
Richard
  • 62,943
  • 126
  • 334
  • 542
  • Try this http://stackoverflow.com/questions/1960473/unique-values-in-an-array – Artem Vyshniakov Sep 07 '12 at 13:10
  • 2
    @Artem - That's a completely different question about getting an array of unique values. – Richard Sep 07 '12 at 13:25
  • Will the initial array always be sorted as is? – sp00m Sep 07 '12 at 13:39
  • Would it be ok to use underscore.js? You could use [`_.pluck`](http://underscorejs.org/#pluck) - although this will probably save you only one or two lines of code (and add the library....), a little like: http://jsfiddle.net/mYxVs/ – m90 Sep 07 '12 at 13:52

1 Answers1

8

you could use map for this purpose as:

var distances = {};
$.map(electrons,function(e,i) {
   distances[e.distance] = (distances[e.distance] || 0) + 1;
});

or

var distances = {};
$.each(electrons,function(i,e) {
   distances[this.distance] = (distances[this.distance] || 0) + 1;
});

Also may I point out to you that although this code good to look and compact, this is not generally faster. Better make your code more faster and more easy to look at as:

var distances = {},e;
for (var i = 0,l=electrons.length; i < l; i++) { 
    e = electrons[i];
    distances[e.distance] = (distances[e.distance] || 0) + 1;
}
Avinash R
  • 3,101
  • 1
  • 27
  • 47
  • You don't need `$.map` here, I'd use `$.each` instead. – gen_Eric Sep 07 '12 at 14:15
  • @Rocket, i used `$.map` coz, that was the first thing that came to my mind at that time, although in this particular context both would serve the purpose of removing the clumsiness. Also i've put the code for the same. – Avinash R Sep 07 '12 at 15:16
  • Thanks! I hadn't seen that use of `||` before - very useful. – Richard Sep 07 '12 at 15:39