Home > Enterprise >  How do I write a function that return the the first number with highest frequency(mode)
How do I write a function that return the the first number with highest frequency(mode)

Time:10-06

I am solving a problem which asks me to return the number with the highest frequency(mode). For example, if arr contains [3, 9, 3, 1, 6] the output should be 3. If there is more than one mode, I want to return the one that appeared first. [6, 6, 3, 3, 5, 5] should return 6 because it appeared first. If there is no mode, I want to return 0. The array will not be empty. I am new to algorithms, please suggest a simpler solution for me.

function Mode(arr) { 
  const arrayObject = {};
 
  arr.forEach(arr => {
      if(!arrayObject[arr]) {
          arrayObject[arr] = 1
        //   console.log(arrayObject)
      } else if(arrayObject[arr]){
          arrayObject[arr]  = 1
        //   console.log(arrayObject)
      }
  })
  console.log(arrayObject) // { '3': 2, '5': 2, '6': 2 } array keys are automatically sorted in ascending other.This could be the problem but I don't know how to unsort the arrays//
  
  let highestValueKey = 0;
  let highestValue = 0
  
  for(let key in arrayObject) {
        const value = arrayObject[key]
        if(value > highestValue) {
          highestValue = value
          highestValueKey = key   
      }
      
  }
     return Number(highestValueKey)
 
}
console.log(Mode([6, 6, 3, 3, 5, 5])) // 3 instead of 6

CodePudding user response:

You could use reduce to count the number of occurrences, then choose the max from there.

I need to step away for a bit, but I'll come back later and explain what's going on in the snippet below. Apologies if it's cryptic in the mean time.

function mode(arr) {
  const counts = arr.reduce((acc, value, index) => {
    acc[value] = (acc[value] || { index, value, count: 0 });
    acc[value].count  ;
    return acc;
  }, {})
  const sorted = Object.values(counts)
    .sort(({count: ca, index: ia}, {count: cz, index: iz}) => (cz - ca) || (ia - iz));
  return sorted[0].value;
}

console.log(mode([6, 6, 3, 3, 5, 5])) // 6
console.log(mode([3, 9, 3, 1, 6])) // 3
console.log(mode([3, 9, 3, 6, 1, 9, 9])) // 9

CodePudding user response:

Just keep track of both count AND when it was first seen.

function mode (arr) {
    const countSeen = {};
    const firstSeen = {};
    for (let i = 0; i < arr.length; i  ) {
        let elem = arr[i];
        if (! countSeen[elem]) {
            countSeen[elem] = 1;
            firstSeen[elem] = i;
        }
        else {
            countSeen[elem]  ;
        }
    }

    let mostSeenCount = 0;
    let mostSeenValue = null;
    for (let elem of Object.keys(countSeen)) {
        if (mostSeenCount < countSeen[elem] ||
            (mostSeenCount == countSeen[elem] && firstSeen[elem] < firstSeen[mostSeenValue])
        ) {
            mostSeenCount = countSeen[elem];
            mostSeenValue = elem;
        }
    }

    return mostSeenValue;
}

console.log(mode([5, 6, 6, 6, 3, 3, 5, 5]))

CodePudding user response:

You could use a Map whose keys are the array values, and the corresponding Map value is the frequency count:

  • Create the map and initialise the counts with 0
  • Increment the count as each input value is visited.
  • Use Math.max to get the greatest count from that map
  • Iterate the map to find the first count that matches that maximum

As Map entries are iterated in insertion order, the correct key will be identified in the last step.

function mode(arr) {
    const counts = new Map(arr.map(i => [i, 0]));
    for (const i of arr) counts.set(i, counts.get(i)   1);
    const maxCount = Math.max(...counts.values());
    for (const [i, count] of counts) {
        if (count == maxCount) return i;
    }
}

console.log(mode([3, 9, 3, 1, 6])); // 3
console.log(mode([6, 6, 3, 3, 5, 5])); // 6
console.log(mode([3, 9, 3, 6, 1, 9, 9])); // 9
console.log(mode([5, 6, 6, 6, 3, 3, 5, 5])); // 5

  • Related