Rubyチュートリアル ~英文小説の最頻出ワードを見つけよう!(その9)
更に欲が出てきました。このtake_byというメソッドを配列でも使いたくなりました。
実は先のsort_byというメソッドはHashクラスにもArrayクラスにも定義されていません。それが定義されているのはEnumerableというモジュールです。モジュールというのはクラスの亜種です。オブジェクトを生成できないクラスです。飛べない鳥ニワトリのようなものです。1
EnumerableモジュールをHashおよびArrayクラスにインクルードすることで、sort_byの夢のコラボが実現しています。
Version07
我らtake_byにも夢を実現させましょう。
module Enumerable
def take_by(nth)
sort_by { |elem| yield elem }.take(nth)
end
end
WORDS = ARGF.read.downcase.scan(/[a-z]+/)
DICTIONARY = WORDS.inject(Hash.new(0)) { |dic, word| dic[word] += 1 ; dic }
p DICTIONARY.take_by(30) { |key, val| -val }
p WORDS.take_by(30) { |n| -n.length }
#> [["the", 16077], ["of", 9823], ["and", 7482], ["to", 7098], ["in", 4456], ["a", 3841], ["that", 3161], ["was", 3040], ["it", 2919], ["i", 2881], ["her", 2550], ["she", 2313], ["as", 2134], ["you", 2071], ["not", 2057], ["be", 2044], ["is", 2033], ["his", 2009], ["he", 1940], ["for", 1927], ["with", 1875], ["on", 1638], ["had", 1567], ["but", 1519], ["s", 1495], ["all", 1363], ["at", 1344], ["by", 1308], ["this", 1249], ["have", 1201]]
["communicativeness", "congregationalist", "indestructibility", "disinterestedness", "misrepresentation", "superciliousness", "unenforceability", "unenforceability", "incomprehensible", "inextinguishable", "discontentedness", "internationalism", "incomprehensible", "unenforceability", "congratulations", "acknowledgments", "accomplishments", "unrighteousness", "condescendingly", "congratulations", "transformations", "merchantibility", "notwithstanding", "congratulations", "recommendations", "appropriateness", "congratulations", "contemporaneous", "comprehensively", "thoughtlessness"]
すばらしい!
配列オブジェクトを指すWORDSに対して、ワード長降順の条件でtake_byメソッドを呼んでいます。
実はわたくし最頻出ワードよりも最長ワードに興味があったのですよ。’incomprehensibleなcongregationalist’になりたい!そんな今日この頃です…
さて…
もう終わりでしょうか?気になる人には気になるところは、もうないでしょうか。
Version08
take_byでよく使いそうなのは、やっぱり最大値最小値でソートしてtakeでしょう。take_byとは別にHashクラスにこれらtop_by_value, bottom_by_valueを定義するというのはどうでしょうか。
module Enumerable
def take_by(nth)
sort_by { |elem| yield elem }.take(nth)
end
end
class Hash
def top_by_value(nth)
take_by(nth) { |key, val| -val }
end
def bottom_by_value(nth)
take_by(nth) { |key, val| val }
end
end
WORDS = ARGF.read.downcase.scan(/[a-z]+/)
DICTIONARY = WORDS.inject(Hash.new(0)) { |dic, word| dic[word] += 1 ; dic }
p DICTIONARY.top_by_value(30)
p DICTIONARY.bottom_by_value(30)
DICTIONARYに対するメソッド呼び出しがすっきりしました。
実行結果は次のようになります。
#> [["the", 16077], ["of", 9823], ["and", 7482], ["to", 7098], ["in", 4456], ["a", 3841], ["that", 3161], ["was", 3040], ["it", 2919], ["i", 2881], ["her", 2550], ["she", 2313], ["as", 2134], ["you", 2071], ["not", 2057], ["be", 2044], ["is", 2033], ["his", 2009], ["he", 1940], ["for", 1927], ["with", 1875], ["on", 1638], ["had", 1567], ["but", 1519], ["s", 1495], ["all", 1363], ["at", 1344], ["by", 1308], ["this", 1249], ["have", 1201]]
[["rained", 1], ["grows", 1], ["pearly", 1], ["hinder", 1], ["overturn", 1], ["interpose", 1], ["infuse", 1], ["prescribes", 1], ["escaping", 1], ["guinness", 1], ["belch", 1], ["humbling", 1], ["appropriately", 1], ["luminous", 1], ["frailty", 1], ["rightful", 1], ["nods", 1], ["purple", 1], ["sepulcher", 1], ["hollow", 1], ["rivaled", 1], ["pearls", 1], ["eyed", 1], ["judaizing", 1], ["fulton", 1], ["taylor", 1], ["coincidence", 1], ["apocalypticae", 1], ["clime", 1], ["atoning", 1]]
ん~
これじゃbottom_by_valueはあまり意味がありませんね。
Version09
ブロックを取って範囲を限定できるようにしたら、もう少しマシになるかもしれません。
module Enumerable
def take_by(nth)
sort_by { |elem| yield elem }.take(nth)
end
end
class Hash
def top_by_value(nth)
select { |key, val| yield val }.take_by(nth) { |key, val| -val }
end
def bottom_by_value(nth)
select { |key, val| yield val }.take_by(nth) { |key, val| val }
end
end
WORDS = ARGF.read.downcase.scan(/[a-z]+/)
DICTIONARY = WORDS.inject(Hash.new(0)) { |dic, word| dic[word] += 1 ; dic }
p DICTIONARY.top_by_value(30) { |val| val < 400 }
p DICTIONARY.bottom_by_value(30) { |val| val > 100 }
top_by_value, bottom_by_valueではselectメソッドを使って、対象範囲を限定できるようにしました。結果に少し意味がでました。
#> [["know", 386], ["up", 383], ["into", 382], ["its", 380], ["did", 378], ["am", 377], ["than", 377], ["little", 376], ["can", 372], ["may", 370], ["how", 365], ["every", 365], ["only", 361], ["man", 361], ["now", 361], ["first", 358], ["other", 358], ["christ", 358], ["should", 353], ["mrs", 352], ["after", 346], ["again", 346], ["come", 344], ["see", 338], ["some", 338], ["well", 329], ["world", 326], ["bennet", 323], ["prophecy", 322], ["never", 317]]
[["gave", 101], ["forth", 101], ["course", 101], ["thy", 102], ["speak", 102], ["get", 102], ["head", 102], ["home", 103], ["bible", 103], ["pleasure", 103], ["seemed", 104], ["together", 105], ["why", 105], ["high", 106], ["thou", 106], ["myself", 106], ["daniel", 108], ["hand", 109], ["near", 109], ["often", 110], ["better", 110], ["hear", 110], ["left", 110], ["believe", 110], ["moment", 111], ["find", 111], ["half", 113], ["really", 114], ["prophet", 114], ["book", 114]]
(次回に続く)
- 説明のためモジュールおよびニワトリに対するこのような差別的発言をお許しください ↩
blog comments powered by Disqus