9

I need to find the number of unique elements in an array.

var myArray = [ 10, 10, 20, 20, 30, 30, 40, 40, 40, 40, 50, 50, 50, 50, 60 ];

I want count = 6 (number of unique elements in array)

And, is there a way to do this without iterating through the array? (I assume that would be the fastest way?).

ANSWER: I used the .filter method as shown below. My actual array element is much more complex. I ended up iterating through my array and created a new array. Each element in the new array was a .substr of the old element. Then, the .filter method below worked great. THANKS to everyone!!

hypermiler
  • 1,719
  • 4
  • 16
  • 25

4 Answers4

12

ES6 offers a single line solution:

new Set(myArray).size
Yukulélé
  • 13,947
  • 10
  • 61
  • 88
Postlagerkarte
  • 5,856
  • 5
  • 29
  • 49
11

You need to keep a set of known values, and an auxilliary count. You can use .reduce():

var count = myArray.reduce(function(values, v) {
  if (!values.set[v]) {
    values.set[v] = 1;
    values.count++;
  }
  return values;
}, { set: {}, count: 0 }).count;

Starting with an empty set of values and a count of zero, this looks at each element to see whether it's been added to the set. If it hasn't, it's added, and the count is incremented.

Pointy
  • 389,373
  • 58
  • 564
  • 602
  • so, in this case it returns count = 6 ? Is it the fastest way? – hypermiler Feb 09 '14 at 16:39
  • 1
    I set up a performance test between your method of reducing vs a vanilla *Object set*: http://jsperf.com/js-set-test – Mr. Polywhirl Feb 09 '14 at 16:50
  • @Mr.Polywhirl For me the "reduce" is faster, but I suspect a big part of that is that the "simple" code is (correctly!) making a `hasOwnProperty` test. Otherwise the two approaches are almost exactly the same, if implemented slightly differently. – Pointy Feb 09 '14 at 18:25
4

How about filter and length:

var len = myArray.filter(function(val, i, arr) { 
    return arr.indexOf(val) === i;
}).length;
David Hellsing
  • 102,045
  • 43
  • 170
  • 208
  • hmmmm. so. what variable? is equal to 6 here? – hypermiler Feb 09 '14 at 16:37
  • 1
    I'm favoring your method for the simple reason that it necessitates less code. Two questions though. 1. is it as fast as the above two methods? and 2. I need some help understanding what (val, i, arr) mean. So, in my case, I need to find the "count" of a substring of an element in the array. So in this case for example, I need to find the number of unique occurrances of myArray.substr(3,6). I'm not sure how this maps to (val, i, arr)... thanks! – hypermiler Feb 09 '14 at 19:01
  • @hypermiler https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter – David Hellsing Feb 09 '14 at 19:41
  • @hypermiler this is simpler, but for long arrays it's going to be expensive. The `.indexOf` operation has to perform a linear search, so the execution time tends to be proportional to the *square* of the length of the array (particularly when there are not many duplicates). – Pointy Feb 09 '14 at 22:19
  • this is a very short array. Maybe max 30 elements. Usually much less. And the likelihood of duplicates is low. – hypermiler Feb 09 '14 at 22:25
  • @David. I really feel bad, this is way above my head. Sorry. I went to mozilla. Still can't get it. I tried to ask another question and was roundly chastised. Deleted the question. – hypermiler Feb 09 '14 at 23:34
1

If you happen to be using lodash:

_.uniq(myArray).length
Dean
  • 711
  • 8
  • 21