4

I am a beginner in JavaScript and I was trying to write code for finding the mode. My code is running but it can find the mode only when it is written consecutively. But when there is an array like this a = [1,2,3,4,5,2], it can not find the mode.

As I am a beginner I do not want to write anything complex but want to learn it in the simplest way. Can anyone please help me in this purpose?

list = [1,2,3,4,5,6,7,7]
var empty = []
i = 0
max = 0
while (i<list.length){

   if (list[i]==list[i+1]){
       empty = list[i] 
   i += 1
    }else{
      i +=1
      }

 }
 document.write(empty) 
ggorlen
  • 44,755
  • 7
  • 76
  • 106
ktas
  • 83
  • 1
  • 2
  • 5

2 Answers2

5

Your code assumes that the parameter array is pre-sorted which is a risky and limiting assumption, and only appears to work on sorted arrays (counterexample: [1,1,1,7,7] incorrectly reports 7 as the mode).

If you wish you persist with this approach, you're on the right track, but you'll need to keep track of the current/best streaks, current/best elements and perform a final check for longest streak before returning the result:

var mode = a => {
  a = a.slice().sort((x, y) => x - y);

  var bestStreak = 1;
  var bestElem = a[0];
  var currentStreak = 1;
  var currentElem = a[0];

  for (let i = 1; i < a.length; i++) {
    if (a[i-1] !== a[i]) {
      if (currentStreak > bestStreak) {
        bestStreak = currentStreak;
        bestElem = currentElem;
      }

      currentStreak = 0;
      currentElem = a[i];
    }

    currentStreak++;
  }

  return currentStreak > bestStreak ? currentElem : bestElem;
};


console.log(mode([1,2,3,4,5,6,7,7]));
console.log(mode([1,1,1,4,5,6,7,7]));
console.log(mode([1,2,3,3,3,6,3,7]));
console.log(mode([1,3,3,4,5,2,2,1]));
console.log(mode([]));

Having said that, sorting is a non-linear operation, so I recommend trying another approach.

The idea is to keep a count of occurrences for each item in the array using an object, then take the element with the highest count. I used reduce to perform these two operations:

const mode = a => 
  Object.values(
    a.reduce((count, e) => {
      if (!(e in count)) {
        count[e] = [0, e];
      }
      
      count[e][0]++;
      return count;
    }, {})
  ).reduce((a, v) => v[0] < a[0] ? a : v, [0, null])[1];
;

console.log(mode([1,2,3,4,5,6,7,7]));
console.log(mode([1,1,1,4,5,6,7,7]));
console.log(mode([1,2,3,3,3,6,3,7]));
console.log(mode([1,3,3,4,5,2,2,1]));
console.log(mode([]));

Or, the same thing, written without reduce for readability:

const mode = a => {
  const count = {};
  
  a.forEach(e => {
    if (!(e in count)) {
      count[e] = 0;
    }

    count[e]++;
  });

  let bestElement;
  let bestCount = 0;

  Object.entries(count).forEach(([k, v]) => {
    if (v > bestCount) {
      bestElement = k;
      bestCount = v;
    }
  });
  
  return bestElement;
};

console.log(mode([1,2,3,4,5,6,7,7]));
console.log(mode([1,1,1,4,5,6,7,7]));
console.log(mode([1,2,3,3,3,6,3,7]));
console.log(mode([1,3,3,4,5,2,2,1]));
console.log(mode([]));

Note that these approaches don't choose the same mode in case of ties. You may wish to add an array to keep track of all modes, or change your algorithm to pick the first or last occurring mode to suit your needs.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • One hiccup, Their is nothing to catch an instance when no mode is found. If no mode is found the function returns the last number in the array instead. – tcanbolat May 21 '21 at 17:21
  • 2
    All (nonempty) arrays have a mode. If all of the elements have the same frequency, I interpret it as OK to return any of them. – ggorlen May 21 '21 at 18:25
2

use a hash

list = [1,2,3,4,5,6,7,7]
counts = {}
list.forEach(function(e) {
  if(counts[e] === undefined) {
    counts[e] = 0
  }
  counts[e] += 1
})

which results in this:

{1:1,2:1,3:1,4:1,5:1,6:1,7:2}

This related question deals with finding the max and min in a hash, which is essentially what you do at the end of this.

Fast way to get the min/max values among properties of object

Nick Ellis
  • 1,048
  • 11
  • 24
  • 1
    In statistics a mode is not a number of occurences but the number with the most occurences. So we are looking for a key not a value. Your solution is great to find the value but not the related key. – Banane Jun 06 '20 at 13:12
  • Thanks for the perspective. It is always good to have a vast of techniques to choose from. – Erik Rybalkin Nov 11 '21 at 16:50