ランキングの集計
リスト中に登場する回数の多い要素トップ N を計算するとき、どんな風に書きますか?
ランキングの集計 - まめめも
via http://d.hatena.ne.jp/sumim/20070619/p2
たとえば、以下のように書きます。
ary = %w(foo bar foo baz foo bar qux foo bar qux quux) n = 3 count = Hash.new(0) ary.each do |e| count[e] += 1 end i = 1 count.keys.sort {|a, b| count[b] <=> count[a] }.first(n).each {|e| puts "#{i}位:" puts "- #{e}" i += 1 }
実行結果です。
1位: - foo 2位: - bar 3位: - qux
と、ここまで書いてから、同数の取り扱いが問題になっていることに気づく。ふえーん。だって例題に同数がないし…。
…こほん。仕切り直し。barを1個追加して同数を作りました。
ary = %w(foo bar foo baz foo bar qux foo bar qux quux bar) n = 3 count = Hash.new(0) ary.each do |e| count[e] += 1 end i = 1 c = -1 count.keys.sort {|a, b| count[b] <=> count[a] }.each {|e| if count[e] != c puts "#{i}位:" c = count[e] end puts "- #{e} (#{count[e]})" i += 1 break if i > n }
実行結果です。
1位: - foo (4) - bar (4) 3位: - qux (2)
追記:id:ku-ma-meさんからバグを指摘していただきました。あらら、本当ですね。わざわざすみません。そうかbreakを間違えていますね。さらに直しました。3位が重複したときの処理も入れました。
ary = %w(foo bar foo baz foo bar qux foo bar qux quux bar xxx xxx) n = 3 count = Hash.new(0) ary.each do |e| count[e] += 1 end i = 1 c = -1 count.keys.sort {|a, b| count[b] <=> count[a] }.each {|e| if count[e] != c break if i > n puts "#{i}位:" c = count[e] end puts "- #{e} (#{count[e]})" i += 1 }
実行結果です。
1位: - foo (4) - bar (4) 3位: - xxx (2) - qux (2)