Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - Find most frequent number in array, even if there are two

Tags:

javascript

If I have an array of numbers and I want to get the one that occurs the most frequent, yet there are two possible answers, Im having trouble sorting that part out. For example, below should return 1 and 7 but I only get 7. Any help is appreciated.

let arr = [1, 1, 2, 3, 4, 5, 6, 7, 7];

function findMode(numbers) {
    let counted = numbers.reduce((acc, curr) => { 
        if (curr in acc) {
            acc[curr]++;
        } else {
            acc[curr] = 1;
        }

        return acc;
    }, {});

    let mode = Object.keys(counted).reduce((a, b) => counted[a] > counted[b] ? a : b);

    return mode;
}

console.log(findMode(arr));
like image 720
Marsel Gray Avatar asked Mar 02 '23 12:03

Marsel Gray


2 Answers

You could group equal items in sub-arrays, then sort by sub-array length and retrieve the first values with the same array length like this:

const arr = [1, 1, 2, 3, 4, 5, 6, 7, 7],
  output = arr
    .sort((a, b) => a - b)
    .reduce(
      (acc, cur, i, { [i - 1]: last }) =>
        (cur === last ? acc[acc.length - 1].push(cur) : acc.push([cur])) && acc,
      []
    )
    .sort((a, b) => b.length - a.length)
    .reduce(
      (a, b, _, { 0: first }) => (first.length === b.length ? [...a, b[0]] : a),
      []
    );

console.log(output);
like image 180
Guerric P Avatar answered Apr 30 '23 07:04

Guerric P


You can use an array as the accumulator.

let arr = [1, 1, 2, 3, 4, 5, 6, 7, 7];

function findMode(numbers) {
    let counted = numbers.reduce((acc, curr) => { 
        if (curr in acc) {
            acc[curr]++;
        } else {
            acc[curr] = 1;
        }

        return acc;
    }, {});

    let mode = Object.keys(counted).reduce((acc, curr) => {
      if(!acc.length || counted[curr] > counted[acc[0]]) return [curr];
      if(counted[curr] === counted[acc[0]]) acc.push(curr);
      return acc;
    }, []);

    return mode;
}
console.log(findMode(arr));

Alternatively, you can find the highest frequency and then use filter to find numbers with that frequency.

let arr = [1, 1, 2, 3, 4, 5, 6, 7, 7];

function findMode(numbers) {
    let counted = numbers.reduce((acc, curr) => { 
        if (curr in acc) {
            acc[curr]++;
        } else {
            acc[curr] = 1;
        }
        return acc;
    }, {});
    let mode = Math.max(...Object.values(counted));
    return Object.keys(counted).filter(x => counted[x] === mode);
}
console.log(findMode(arr));
like image 39
Unmitigated Avatar answered Apr 30 '23 06:04

Unmitigated