Учитывая массив чисел, мне нужно найти число с наибольшей частотой и вернуть его. Если есть два или более числа с одинаковой самой высокой частотой, мне нужно вернуть самое большое число.
Ниже приведен код, который я написал.
const numbers = [1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 1, 6, 7, 5];
const numArr = [12, 20, 5, 4, 10, 10, 10, 5, 4, 5, 3, 2];
function frequency(array) {
let object = {}
let maxCount = 0;
let result = 0;
for (let num of array) {
if (object.hasOwnProperty(num)) {
object[num] = object[num] + 1;
}
else object[num] = 1;
}
console.info(object)
let entry = Object.entries(object)
for (const [key, val] of entry) {
if (maxCount < val) {
maxCount = val;
result = key;
}
}
for (const [key, val] of entry) {
result = maxCount === val && key > result ? key : result;
}
return [result, maxCount];
}
const [res, count] = frequency(numArr);
console.info(`number with highest freq: ${res}\nfrequency: ${count}`)Функция frequency работает с массивами, содержащими однозначные числа (например, numbers). Но он не дает правильного вывода с массивами, содержащими двузначные числа (например, numArr)
Приведенный выше код должен выводить 10 как число с самой высокой частотой и 3 как его частоту. Но он выводит 5 и 3 соответственно. Почему это? Связано ли это со значениями ASCII? Спасибо за ваше время.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Ключи уже отсортированы, и если вы хотите получить наивысший «результат», вам нужно изменить maxCount < val на maxCount <= val,, где более высокий ключ заменит более низкий ключ при одинаковых частотах.
Кроме того, вам не нужна последняя петля. Это ничего не делает, кроме как портит ваш код.
const numbers = [1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 1, 6, 7, 5];
const numArr = [12, 20, 5, 4, 10, 10, 10, 5, 4, 5, 3, 2];
function frequency(array) {
let object = {}
let maxCount = 0;
let result = 0;
for (let num of array) {
if (object.hasOwnProperty(num)) {
object[num] = object[num] + 1;
}
else object[num] = 1;
}
console.info(object)
let entry = Object.entries(object)
for (const [key, val] of entry) {
// if (maxCount < val) {
if (maxCount <= val) {
maxCount = val;
result = key;
}
}
/*
for (const [key, val] of entry) {
result = maxCount === val && key > result ? key : result;
}*/
return [result, maxCount];
}
const [res, count] = frequency(numArr);
console.info(`number with highest freq: ${res}\nfrequency: ${count}`)Наконец, вы сможете решить эту проблему, используя только один цикл.
const numbers = [1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 1, 6, 7, 5];
const numArr = [12, 20, 5, 4, 10, 10, 10, 5, 4, 5, 3, 2];
function frequency(array) {
let object = {};
let hasHigherFrequency = false, hasEqualFrequencyButHigherValue = false;
let highestFrequency = {
res: 0,
count: 0
};
for (let num of array) {
if (object.hasOwnProperty(num)) {
object[num] = object[num] + 1;
}
else object[num] = 1;
hasHigherFrequency = object[num] > highestFrequency.count;
hasEqualFrequencyButHigherValue = object[num] == highestFrequency.count && num > highestFrequency.res;
if (hasHigherFrequency || hasEqualFrequencyButHigherValue) {
highestFrequency = {res: num, count: object[num]};
}
}
console.info(object);
return highestFrequency;
}
const {res, count} = frequency(numArr);
console.info(`number with highest freq: ${res}\nfrequency: ${count}`)Ключи в объектах всегда представляют собой строки или символы, а не числа. Для большей части вашего кода это нормально, но это проблема в двух циклах for-of над Object.entries, поскольку key будет строка, и в конечном итоге вы установите result в строку. Во втором цикле key > result — это сравнение строк, при котором выполняется поразрядное, а не числовое сравнение.
Вместо использования объекта для подсчета используйте Map. Map ключи могут быть реальными цифрами. См. статью MDN на Map, чтобы узнать рекомендации о том, когда использовать объекты, а не карты.
const numbers = [1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 1, 6, 7, 5];
const numArr = [12, 20, 5, 4, 10, 10, 10, 5, 4, 5, 3, 2];
function frequency(array) {
let map = new Map();
let maxCount = 0;
let result = 0;
for (let num of array) {
const value = map.get(num) ?? 0;
map.set(num, value + 1);
}
console.info([...map]);
for (const [key, val] of map) {
if (maxCount < val) {
maxCount = val;
result = key;
}
}
for (const [key, val] of map) {
result = maxCount === val && key > result ? key : result;
}
return [result, maxCount];
}
const [res, count] = frequency(numArr);
console.info(`number with highest freq: ${res}\nfrequency: ${count}`);Здесь понадобится всего 1 петля, просто сравнивайте с максимумом, пока собираете отсчеты. Таким образом, вам также не нужно заботиться о преобразовании числа/строки для результата:
const numArr = [12, 20, 5, 4, 10, 10, 10, 5, 4, 5, 3, 2];
function frequency(array) {
const object = {};
let maxCount = 0, result = 0;
for (const num of array) {
const val = object[num] = (object[num] ?? 0) + 1;
if (maxCount < val) maxCount = val, result = num;
else if (maxCount === val && result < num) result = num;
}
return [result, maxCount];
}
const [res, count] = frequency(numArr.sort().reverse());
console.info(`number with highest freq: ${res}\nfrequency: ${count}`)@RickardElimää, спасибо, исправлено, я пропустил это в вопросе, думал, что требование проще
Теперь вы заслужили мой +1. :D
Если вы запустите
frequency(numArr.sort().reverse()), он вернет 5 в качествеres. Также нужно учитыватьnum.