Hatena::ブログ(Diary)

まめめも このページをアンテナに追加 RSSフィード

2007-06-14

[] ランキングの集計

リスト中に登場する回数の多い要素トップ N を計算するとき、どんな風に書きますか?

順序統計量の話がしたいわけではなく、そういうコードは頻繁に書くわりに、書き方に納得できなくていつも悩んでいるのです。短く、かつ、わかりやすい書き方がポイント高いです (効率は軽視) 。普段は以下のように書いているけど、これは長すぎかつ難解で納得できてません。

ary = %w(foo bar foo baz foo bar qux foo bar qux quux)
n = 3

# 回数をカウントする
count = Hash.new { 0 }
ary.each {|x| count[x] += 1 }

# (文字列 -> 回数) のハッシュを反転して (回数 -> [文字列]) にする
rev_count = {}
count.each {|k, v| (rev_count[v] ||= []) << k }

i = 1
# 回数の大きい順に回す
rev_count.keys.sort.reverse.each do |v|
    # 順位を数えながら出力する
    puts "#{ i } 位:"
    rev_count[v].each {|k| puts "- #{ k }" }
    i += rev_count[v].size
    break if i > n
end

ここで悩むのは Hash クラスに何かメソッドが足りてないサインではないか (自分中心的な発想) 。

n_shuyon_shuyo 2007/06/19 18:54 http://d.hatena.ne.jp/n_shuyo/20070619/ruby これの「単語数カウント」でどうでしょう? 順位は出していませんが……

ku-ma-meku-ma-me 2007/06/19 20:56 なるほど、.inject(Hash.new(0)) {|h,w| h[w] += 1; h } というイディオムは思いつきませんでした。.to_a は要らないかも。ありがとうございます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証