はじめに
次章1つ目。
問題
ある値の集合のなかで、最も頻繁に登場する値のことを統計では「モード」と呼ぶ。
調査データの配列を処理するコードを書いてみよう。
調査対象が質問に1〜10のいずれかの数値でこたえているので、そこからモードを求めたい。
モードが複数存在する場合は、いずれかの値を選択する。
解答
テストデータ。
array1 = [1,2,1,1,1,3,5,7,9,10,1,1,4,5,2,2,2,3,2,4,2,7,2]
array2 = [2,5,4,3,2,1,6,8]
array3 = [7,5,7,7,8,9,1,1,3,10,2,6,8]
def check_mode(array)
sorted_array = array.sort
current_num = nil
mode = nil
max_count = 0
count = 1
sorted_array.each do |i|
if current_num != i
if max_count < count
max_count = count
mode = current_num
end
current_num = i
count = 1
else
count += 1
end
end
mode
end
答えは合ってる。
puts check_mode(array1)
=> 2
puts check_mode(array2)
=> 2
puts check_mode(array3)
=> 7
でももっとシンプルにする方法はあるんだろうな、いくらなんでもこれは無いな…と思った。
なので調べた。
調べてみたらこんなやり方もあるって書いてあった。
array1.group_by { |e| e }.sort_by { |e, v| -v.size }.map(&:first).first
array1.max_by{ |a| array1.count(a) }
なんだかよくわからなかったので調べる。
1個ずつバラバラに動かしてみる。
バラすとどうなってるのかよく分かる。
なるほどー。
p array1.group_by{ |e| e }
=> {1=>[1, 1, 1, 1, 1, 1], 2=>[2, 2, 2, 2, 2, 2, 2], 3=>[3, 3], 5=>[5, 5], 7=>[7, 7], 9=>[9], 10=>[10], 4=>[4, 4]}
p array1.group_by{ |e| e }.sort_by{ |e, v| -v.size }
=> [[2, [2, 2, 2, 2, 2, 2, 2]], [1, [1, 1, 1, 1, 1, 1]], [7, [7, 7]], [5, [5, 5]], [3, [3, 3]], [4, [4, 4]], [10, [10]], [9, [9]]]
p array1.group_by{ |e| e }.sort_by{ |e, v| -v.size }.map(&:first)
=> [2, 1, 7, 5, 3, 4, 10, 9]
p array1.group_by{ |e| e }.sort_by{ |e, v| -v.size }.map(&:first).first
=> 2
2つ目の方も。
array1.count(e)
の結果が最大のものが返ってくる。
シンプル。とてもシンプル。
p array1.max_by{ |e| e }
=> 10
p array1.count(1)
=> 6
p array1.max_by{ |e| array1.count(e) }
=> 2
便利なのいっぱい。
パッと使えるようになれるようがんばろう。
問題の出典
- プログラマの考え方がおもしろいほど身につく本 問題解決能力を鍛えよう!