ブログ

読んで思い出す。忘れるために書く

英文から母音の数をカウントして多い順に並べる (Ruby)

英文から母音の数をカウントして多い順に並べる」という Python の質問を目にしたので Ruby で書いてみた

「最初に動くものを書き、段階的に磨き上げていく」というのはコードを書く上でよくやることなので、今回はその初稿を残しておく

この時点でテストコードを併せて書いておくと、 (壊れたかどうかはテストコードが確認してくれるので) 「こうしたほうがより良いのではないか」の試行錯誤に集中しやすくなる

target_text = <<EOF
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOF

# 母音をカウントする proc 群
count_targets = [
  proc { |word| word.chars.select { |w| w.eql?('a') }.size },
  proc { |word| word.chars.select { |w| w.eql?('e') }.size },
  proc { |word| word.chars.select { |w| w.eql?('i') }.size },
  proc { |word| word.chars.select { |w| w.eql?('o') }.size },
  proc { |word| word.chars.select { |w| w.eql?('u') }.size },
]

# ぜんぶ小文字化して、単語ごとに配列に分離
target_words =
  target_text.split(' ')
             .map { |word| word.downcase }

# count_targets を使って対象となる文字数をカウント
count_results =
  count_targets.map do |detector|
    target_words.map do |word|
      detector.call(word)
    end.reduce(&:+)
  end

# カウント結果を母音と合成して key/value 形式に変換
labels = %w[a e i o u]
pp labels.zip(count_results)
         .to_h
         .sort_by { |_key, count| -count } # カウント数をもとに降順に並べ替え
         .to_h  # sort_by で配列の組み合わせに変換されるのでまた to_h する
# =>
#   {
#     "i"=>42,
#     "e"=>38,
#     "a"=>29,
#     "o"=>29,
#     "u"=>29
#   }

最初の段階とはいえ、 count_targets に代入している proc はコピペしすぎ

なので、次の段階としては関数定義に変換して共通部分をまとめてあげるといいかもしれない

# TIPS: map のなかで関数を呼び出したいときは次のような定義と書き方ができる

def foo(char)
  print char
end

%w[a b c].map(&method(:foo)) # => abc

Links