Sun, 03 Jun 2012 (平成24年) [長年日記]
_ Ruby ぽいコードの書き方とは
昨日の大場さんのお話にあった「Ruby ぽいコーディングは for や each を使うのではなく、そこは map や collect を使う」というのを聞いて、for は使わないけど each は未だによく使ってしまうよなと思ったので、どうしたらいいのか考えた。
Apache の access.log から POST リクエストを送ってきたアクセスの IP アドレスだけ拾おうとするとこう書いてしまう
ARGF.each{|line| puts line.scan(/^.*?\s/) if /POST/ =~ line}
のを、こう書けばいいということか。
puts ARGF.select{|line| /POST/ =~ line}.map{|line| line.scan(/^.*?\s/)}
あぁ、こう書くと拾い出したものを使いまわそうとして
result = [] ARGF.each{|line| result << line.scan(/^.*?\s/) if /POST/ =~ line} result = result.uniq
とか書いて、汚いコードだなといつも思うパターンが
result = ARGF.select{|line| /POST/ =~ line}.map{|line| line.scan(/^.*?\s/)}.uniq
とすっきり書けるんだということに今頃気づいて感動してるところ。恥ずかし……
追記: こうすればもっと簡単になるのか。
result = ARGF.grep(/POST/).map{|line| line.scan(/^.*?\s/)}.uniq
最後のuniq前に大きな中間Arrayが生成されてしまうので、lazyを使ってそれが抑制できるといいですな。