function rank(arr, f) {
return arr
.map((x, i) => [x, i])
.sort((a, b) => f(a[0], b[0]))
.reduce((a, x, i, s) => (a[x[1]] =
i > 0 && f(s[i - 1][0], x[0]) === 0 ? a[s[i - 1][1]] : i + 1, a), []);
}
使用法:
rank([79, 5, 18, 5, 32, 1, 16, 1, 82, 13], (a, b) => b - a);
// [2, 7, 4, 7, 3, 9, 5, 9, 1, 6]
少し見苦しいように見えますが、オブジェクト/マップを使用しないため、実行速度が少し速くなるだけでなく、さらに重要なことに、比較関数indexOf()
で定義された「同じランク」の意味を尊重します。またはオブジェクトを使用する場合、「同じランク」はまたはを意味するだけです。indexOf()
a === b
String(a) === String(b)
または、次を使用しますfindIndex()
。
function rank(arr, f) {
const sorted = arr.slice().sort(f)
return arr.map(x => sorted.findIndex(s => f(x, s) === 0) + 1)
}