Я был полон решимости дать общую c параметризованную функцию, где номер не жестко запрограммирован.
В вашем примере используются два жестко запрограммированных значения:
- секунда должна быть выбрана минимальная частота
- В случае ничьей следует выбрать значение второе наименьшее
Следующий код работает следующим образом:
- Получить частоту каждого входного значения
- Сгруппировать вместе все значения с одинаковой частотой.
- Отсортируйте эти сгруппированные пары по частоте и выберите n-е наименьшее (в вашем case,
n=2
) - Если n-я самая низкая частота имеет несколько пар, отсортируйте эти пары по значению и выберите m-ю самую низкую пару (в вашем случае
m=2
) - Возвращает значение этой последней пары
Параметры m
и n
, на которые я здесь ссылаюсь, в коде называются freqInd
и valInd
. Обратите внимание, что для выбора второй самой низкой частоты freqInd
должно быть 1
, а не 2
(поскольку 0
выберет самую низкую частоту, и, следовательно, 1
выберет вторую самую низкую).
let lowestFreqVal = (freqInd, valInd, values) => {
// Calculate frequencies in a map
let f = new Map();
for (let v of values) f.set(v, (f.get(v) || 0) + 1);
// Group together all val/freq pairs with the same frequency
let ff = new Map();
for (let [ val, freq ] of f) ff.set(freq, (ff.get(freq) || []).concat([ val ]));
// Sort these groups by frequency
let byFreq = [ ...ff ].sort(([ freq1 ], [ freq2 ]) => freq1 - freq2);
// Here are all the items of the `freqInd`-th lowest frequency, sorted by value
// Note that `[1]` returns an array of integers at the frequency, whereas `[0]` would return the frequency itself
let lowestItems = byFreq[ Math.min(byFreq.length - 1, freqInd) ][1]
.sort((v1, v2) => v1 - v2);
// Return the `valInd`-th lowest value
return lowestItems[ Math.min(lowestItems.length - 1, valInd) ];
};
console.log('Some random examples:');
for (let i = 0; i < 10; i++) {
// An array of random length, full of random integers
let arr = [ ...new Array(3 + Math.floor(Math.random() * 5)) ]
.map(v => Math.floor(Math.random() * 4));
// Show the result of `lowestFreqVal` on this random Array
console.log(`lowestFreqVal(1, 1, ${JSON.stringify(arr)}) = ${lowestFreqVal(1, 1, arr)}`);
}
Это не оптимальное решение, так как используется sort
. Известно, что проблема нахождения некоторого n-го максимального значения в списке может быть реализована для обеспечения лучшего времени выполнения, чем sort
(и значительно лучшего времени выполнения, когда n
является небольшим значением - мы можем видеть это интуитивно, потому что если n=0
, единственный проход (O(n)
) делает свое дело).