27
var store = ['1','2','2','3','4'];

I want to find out that 2 appear the most in the array. How do I go about doing that?

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
p0larBoy
  • 1,312
  • 5
  • 15
  • 24
  • 3
    is that array always sorted (as it is in your example)? – Thilo Sep 24 '10 at 03:02
  • 1
    See here for my pseudo-code answer: http://stackoverflow.com/questions/3774757/c-get-mode-from-list-of-integers/3774791#3774791 – paxdiablo Sep 24 '10 at 03:06
  • 1
    If the answer to @Thilo's question is yes, same elements will always be grouped together. This allows you to loop through the list once comparing each item to the previous one and keeping a count of how many same elements you've encountered and the highest run encountered along the way. At the end of the loop, you'll have your answer. This will run in linear time. If the answer to @Thilo's question is no, then sort the list first, followed by the strategy above. – Asaph Sep 24 '10 at 03:09
  • @Asaph: if the array is not sorted, codaddict's algorithm is better than sorting (if you can spare the extra memory for the frequency counters) – Thilo Sep 24 '10 at 03:12
  • @Thilo: True. It's a little better. But sorting is not such a big expense. @codaddict's algorithm runs in linear space and linear time. My suggestion runs in constant space and O(n log n + n) time, depending on sorting algorithm. – Asaph Sep 24 '10 at 03:22
  • @Thilo nope it isn't but i guess i can make it sort in this manner according @Asaph – p0larBoy Sep 24 '10 at 04:48
  • If the `2` appears more than `N/2` times, this can solved in `O(n)` using `Boyer-Moore Majority Voting Algorithm` – st0le Sep 25 '10 at 13:43
  • Does this answer your question? [Get the element with the highest occurrence in an array](https://stackoverflow.com/questions/1053843/get-the-element-with-the-highest-occurrence-in-an-array) – user202729 Jan 20 '21 at 09:06

13 Answers13

32

I would do something like:

var store = ['1','2','2','3','4'];
var frequency = {};  // array of frequency.
var max = 0;  // holds the max frequency.
var result;   // holds the max frequency element.
for(var v in store) {
        frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
        if(frequency[store[v]] > max) { // is this frequency > max so far ?
                max = frequency[store[v]];  // update max.
                result = store[v];          // update result.
        }
}
codaddict
  • 445,704
  • 82
  • 492
  • 529
  • 1
    +1 - Very nice... But I would use a `for` loop to block corner cases where the array object has properties: http://jsfiddle.net/9eJd3/ – Peter Ajtai Sep 24 '10 at 03:21
  • I'd suggest the addition of `if (store.hasOwnProperty(v))` in case someone has decided to modify Object or Array's prototype, as folks seem to be somewhat keen on that doing around here ;P – Dagg Nabbit Sep 24 '10 at 03:26
  • @no - That's not good enough, since `store` can have its own properties that **are not** values of the array. ( http://jsfiddle.net/vR5JK/ ). A `for` loop will do the trick though, since anything outside the values in the array are not included in `store[0]` to `store[store.length]` – Peter Ajtai Sep 24 '10 at 03:29
  • Ooops, by `for` loop I meant `for(var v=0; v < store.length; ++v){...}`. – Peter Ajtai Sep 24 '10 at 03:33
  • @Peter Ajtai - I saw your example, but that would actually be the behavior I'd expect... I'd want every property of the array object counted, regardless of whether the property also represents an array index. That way it can work for regular objects too. I guess it depends on what behavior you want. – Dagg Nabbit Sep 24 '10 at 03:35
  • On the other hand I'd definitely *not* want cute function properties that someone added to Array.prototype or Object.prototype to show up. Just sayin. – Dagg Nabbit Sep 24 '10 at 03:36
  • @no - Methods can be added directly to an array and not to Array.prototype: http://jsfiddle.net/YHFqJ/ ---- But yeah, it just depends on your view of what an "Array" is... Guess I'm not as open mined as you ;) – Peter Ajtai Sep 24 '10 at 03:45
  • @Peter Ajtai: sure, but I'm hoping nobody would ever _do_ that... and if they are, maybe they're adding the same function more than once and they want to see which one occurs the mosst times ;p – Dagg Nabbit Sep 24 '10 at 03:59
7

Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.

Edit: Proposal with one loop, only.

var store = ['1', '2', '2', '3', '4', '5', '5'],
    distribution = {},
    max = 0,
    result = [];

store.forEach(function (a) {
    distribution[a] = (distribution[a] || 0) + 1;
    if (distribution[a] > max) {
        max = distribution[a];
        result = [a];
        return;
    }
    if (distribution[a] === max) {
        result.push(a);
    }
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
5
arr.sort();
    var max=0,result,freq = 0;
    for(var i=0; i < arr.length; i++){
        if(arr[i]===arr[i+1]){
            freq++;
        }
        else {
            freq=0;
        }
        if(freq>max){
            result = arr[i];
            max = freq;
        }
    }
    return result;
Ashikodi
  • 1,090
  • 1
  • 9
  • 9
  • As there are many other answers, it might be helpful to add an explanation as to why your solution is preferable. You can add an explanation by clicking the "edit" button... – Brian Tompsett - 汤莱恩 May 25 '15 at 15:34
  • 1
    Does arr.sort() always sort group of different types in array correctly? – user2734550 May 26 '15 at 06:51
  • 1
    yes @ user2734550. arr.sort() is able to sort group of different types in array correctly. but if you are dealing with single together with muliple digit numbers, you may need to sort this way: arr.sort(function(a,b){return a- b;}) – Ashikodi May 26 '15 at 07:25
  • 1
    Thank you. I really like your solution! simple to read and easy to understand. Works for strings too. – user2734550 May 26 '15 at 07:28
  • I like your solution because it uses more basic JavaScript instructions that are common to most C-family languages. – Jason210 Dec 01 '16 at 18:31
2

Make a histogram, find the key for the maximum number in the histogram.

var hist = [];
for (var i = 0; i < store.length; i++) {
  var n = store[i];
  if (hist[n] === undefined) hist[n] = 0;
  else hist[n]++;
}

var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
  if (hist[store[i]] > best_count) {
    best_count = hist[store[i]];
    best = store[i];
  }
}

alert(best + ' occurs the most at ' + best_count + ' occurrences');

This assumes either there are no ties, or you don't care which is selected.

Jamie Wong
  • 18,104
  • 8
  • 63
  • 81
2

Another ES6 option. Works with strings or numbers.

function mode(arr) {
  const store = {}
  arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
  return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
gazanther
  • 41
  • 1
  • 3
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Ethan Jun 05 '22 at 02:54
1

If the array is sorted this should work:

function popular(array) { 
   if (array.length == 0) return [null, 0];
   var n = max = 1, maxNum = array[0], pv, cv;

   for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
      if (pv == cv) { 
        if (++n >= max) {
           max = n; maxNum = cv;
        }
      } else n = 1;
   }

   return [maxNum, max];
};

popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]

popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
Cristian Sanchez
  • 31,171
  • 11
  • 57
  • 63
  • The values don't need to be ordered, just grouped. Fewer comparisons arise if the current _mode candidate_'s frequency is checked `if (pv != cv)`. – greybeard Mar 10 '15 at 07:53
  • @greybeard, does arr.sort() do 'grouping' well? I know it doesn't sort so well for different types, but does it do grouping correctly? – user2734550 May 26 '15 at 07:05
0

I solved it this way for finding the most common integer

function mostCommon(arr) {
    // finds the first most common integer, doesn't account for 2 equally common integers (a tie)

    freq = [];

    // set all frequency counts to 0
    for(i = 0; i < arr[arr.length-1]; i++) {
      freq[i] = 0;
    }

    // use index in freq to represent the number, and the value at the index represent the frequency count 
    for(i = 0; i < arr.length; i++) {
      freq[arr[i]]++; 
    }

    // find biggest number's index, that's the most frequent integer
    mostCommon = freq[0];
    for(i = 0; i < freq.length; i++) {
      if(freq[i] > mostCommon) {
        mostCommon = i;
      }
    }

    return mostCommon;
} 
Zack
  • 1,615
  • 18
  • 26
0

This is my solution.

var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
    if ( arr[i] !== prev ) {
        a.push(arr[i]);
        b.push(1);
    } else {
        b[b.length-1]++;
    }
    prev = arr[i];
}


var max = b[0]
for(var p=1;p<b.length;p++){
       if(b[p]>max)max=b[p]
 }

var indices = []
for(var q=0;q<a.length;q++){
   if(b[q]==max){indices.push(a[q])}
}
return indices;

};

Reza
  • 2,896
  • 4
  • 26
  • 37
0

This version will quit looking when the count exceeds the number of items not yet counted.

It works without sorting the array.

Array.prototype.most= function(){
    var L= this.length, freq= [], unique= [], 
    tem, max= 1, index, count;
    while(L>= max){
        tem= this[--L];
        if(unique.indexOf(tem)== -1){
            unique.push(tem);
            index= -1, count= 0;
            while((index= this.indexOf(tem, index+1))!= -1){
                ++count;
            }
            if(count> max){
                freq= [tem];
                max= count;
            }
            else if(count== max) freq.push(tem);
        }
    }
    return [freq, max];
}

    //test
    var A= ["apples","oranges","oranges","oranges","bananas",
   "bananas","oranges","bananas"];
    alert(A.most()) // [oranges,4]

    A.push("bananas");
    alert(A.most()) // [bananas,oranges,4]
kennebec
  • 102,654
  • 32
  • 106
  • 127
0

All the solutions above are iterative.

Here's a ES6 functional mutation-less version:

Array.prototype.mostRepresented = function() {
  const indexedElements = this.reduce((result, element) => {
    return result.map(el => {
      return {
        value: el.value,
        count: el.count + (el.value === element ? 1 : 0),
      };
    }).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
  }, []);
  return (indexedElements.slice(1).reduce(
    (result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
    indexedElements[0]) || {}).value;
};

It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.

The last line could be replaced with:

  return (indexedElements.maxBy(el => el.count) || {}).value;

With:

Array.prototype.maxBy = function(fn) {
  return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};

for clarity

Augustin Riedinger
  • 20,909
  • 29
  • 133
  • 206
-1

If the array contains strings try this solution

    function GetMaxFrequency (array) {
    var store = array;
    var frequency = [];  // array of frequency.
    var result;   // holds the max frequency element.

    for(var v in store) {
        var target = store[v];
        var numOccurences = $.grep(store, function (elem) {
        return elem === target;
        }).length;
        frequency.push(numOccurences);

    }
    maxValue = Math.max.apply(this, frequency);
    result = store[$.inArray(maxValue,frequency)];
    return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
yahya akhtar
  • 239
  • 3
  • 16
-1

A fairly short solution.

function mostCommon(list) {
  var keyCounts = {};
  var topCount = 0;
  var topKey = {};
  list.forEach(function(item, val) {
    keyCounts[item] = keyCounts[item] + 1 || 1;
    if (keyCounts[item] > topCount) {
      topKey = item;
      topCount = keyCounts[item];
    }
  });

  return topKey;
}

document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
Cheyne
  • 1,964
  • 4
  • 27
  • 43
-1

This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.

    function mode(numbers) {
      var counterObj = {}; 
      var max = 0;
      var result = [];
      for(let num in numbers) {
        counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1; 
        if(counterObj[numbers[num]] >= max) { 
          max = counterObj[numbers[num]];
        }
      }
      for (let num in counterObj) {
        if(counterObj[num] == max) {
          result.push(parseInt(num));
        }
      }
      return result;
    }
Collin Rea
  • 23
  • 5