Averages/Mode : improve/optimize my solution

Tell us what’s happening:
so this problem was a bit trickier than it looks but I was able to solve it with the solution below. However, I feel there must be a simpler way to solve this…

Your code so far


function mode (arr) {
  let countObj = {}
  for (let i = 0 ; i < arr.length; i++){
    countObj[arr[i]] = (countObj[arr[i]] || 0) +1 
  }
  let countArr = Object.entries(countObj)
  let maxValue = Math.max.apply(null, countArr.map((x)=>x[1]))
  let modeValue = []
  for (let k in countObj){
    if (countObj[k] === maxValue){
		  modeValue.push(Number(k))
    }
  }

  return modeValue

}

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/coding-interview-prep/rosetta-code/averagesmode/

function mode(arr) {
  let count, mode_number;
  for (let item of arr) {
    let _count = arr.filter(i => i == item).length;
    if (_count > count) {
      count = _count;
      mode_number = item;
    }
  }
  return mode_number;
}

gonna try to get it down even more

function mode(arr) {
  let count = {};
  arr.map(num => (count[num] = arr.filter(i => i == num).length));
  const max = Math.max(...Object.values(count).filter(i => i));
  return parseInt(Object.keys(count).filter(i => count[i] == max)[0]);
}

savage

here’s an equivalent solution from a complexity standpoint, using Array methods goodness for more readability.

function mode (arr) {
  let count = arr.reduce((count, el) => count.set(el, (count.get(el) || 0) + 1), new Map())
  let max = Math.max(...count.values())
  return [...count.entries()]
          .filter(([_, count]) => count === max)
          .map(([key]) => key)
}

ps:

  1. using iterators adds more overhead from a performance standpoint
  2. using Maps comes in handy when you want to have some non-String keys.

This is just a single pass over the array at best (I think I can optimise away the set iteration as well but trying to figure out how):

function mode (ints) {
  const frequencies = {};
  let modalFreq = 0;
  const modes = new Set();
  
  for (const i of ints) {
    // Set or increment the frequency map value:
    frequencies[i] = (i in frequencies) ? frequencies[i] + 1 : 1;
    // Update the max value if necessary:
    modalFreq = (frequencies[i] > modalFreq) ? frequencies[i] : modalFreq;
    // Add the current value to the Set:
    modes.add(i);
    // If the modes Set only has one value, that's the mode:
    if (modes.size > 1) {
      // Otherwise delete any values that have a frequency < current
      // target frequency, leaving only the values that match the target
      modes.forEach((n) => {
        if (frequencies[n] < modalFreq) modes.delete(n);
      });
    }
  }
  
  return Array.from(modes);
}