Javaで、よくやる順位付け(ランキング)、
TreeMapを使って順位を生成する関数を作ってみる。
スコアをリストで持っているとして、ここでは乱数でリストを用意。
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
list.add(random.nextInt(10));
}
で、Mapを生成する関数を作った。返されるMapはscoreをキーに値が順位になっています。 { score => rank, ... }
ascending: 昇順ならtrue、降順ならfalse
rankWithoutSkipping: 同一順位の後、順位をスキップさせたくないならtrue
public static Map<Integer, Integer> makeRankMap(Collection<Integer> scores,
boolean ascending,
boolean rankWithoutSkipping)
{
TreeMap<Integer, Integer> map = new TreeMap<>(ascending ? null : Collections.reverseOrder());
for (int score : scores) {
map.put(score, map.getOrDefault(score, 0) + 1);
}
if (rankWithoutSkipping) {
int rank = 1;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
entry.setValue(rank++);
}
return map;
}
int rank = 1;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
rank += entry.setValue(rank);
}
return map;
}
最初にスコアをキーにしたTreeMapを作成する。
降順の場合はCollections.reverseOrder()をコンストラクタに渡すようにしています。
キーに対しての値には、同じスコアが何個あるかを一時的に記憶しておきます。
TreeMapなので、キーの値によって既に昇順または降順に保持されています。
rankWithoutSkipping:trueの場合は、単純に順番にランク付けしていくだけです。
rankWithoutSkipping:falseの場合は、同じスコアの所持数に応じてランク付けしていきます。
使う時は、scoreを使ってgetすれば、順位付けしたランクが取得できます。
rankWithoutSkipping: false で実行した例
Map<Integer, Integer> rankMap = makeRankMap(list, false, false);
list.sort((a, b) -> b - a);
for (int score : list) {
System.out.printf("rank:%d, score:%d\n", rankMap.get(score), score);
}
/* --- output ---
rank:1, score:9
rank:1, score:9
rank:3, score:8
rank:4, score:7
rank:5, score:6
rank:6, score:5
rank:6, score:5
rank:8, score:3
rank:9, score:2
rank:9, score:2
------------------- */
rankWithoutSkipping: true で実行した例
Map<Integer, Integer> rankMap = makeRankMap(list, false, true);
list.sort((a, b) -> b - a);
for (int score : list) {
System.out.printf("rank:%d, score:%d\n", rankMap.get(score), score);
}
/* --- output ---
rank:1, score:9
rank:1, score:9
rank:2, score:8
rank:3, score:7
rank:4, score:6
rank:5, score:5
rank:5, score:5
rank:6, score:3
rank:7, score:2
rank:7, score:2
------------------- */
0 件のコメント:
コメントを投稿