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 件のコメント:
コメントを投稿