最大値をもつものを集める(Ruby)

例えば都道府県名をローマ字化したものから、文字数の最大値と、その文字数をもつすべての県名を得たいとする。そのとき、こんなメソッドを作ってみるといいかも知れない。
 

module ExEnumerable
  refine Enumerable do
    def max_select
      pool = []
      max_num = -Float::INFINITY
      each do |i|
        n = yield(i)
        if n > max_ num
          max_ num = n
          pool = [i]
        elsif n == max_ num
          pool << i
        end
      end
      [max_ num, pool]
    end
  end

  [Array, Enumerator, Hash].each {|mdl| mdl.include Enumerable}
end

Enumerable#max_selectは、ブロックの返り値の最大値(max_num)を求めて、そのような最大値になるようなものをレシーバーから集め(pool)、[max_num, pool]を返す。

これを使って、最初の課題を解いてみる。

require "open-uri"
using ExEnumerable

url = "https://gist.githubusercontent.com/koseki/38926/raw/671d5279db1e5cb2c137465e22424c6ba27f4524/todouhuken.txt"
prefectures = URI.open(url).each_line.map {|l| l.chomp.split.last}
prefectures.max_select(&:size)
#=>[9, ["fukushima", "yamanashi", "hiroshima", "yamaguchi", "tokushima", "kagoshima"]]

9文字が最大値だとわかる。県名のリストも返ってくる。


※参考
Ruby で関数型プログラミングっぽく(コピペ) + Haskell 版 - Camera Obscura