mecab-rubyでテキストを形態素解析するときによく使うMeCab::Tagger#parseToNodeですが,戻り値がMeCab::NodeのArrayやEnumeratorではなく,以下のようにMeCab::Node#nextを使って各要素にアクセスしなければならないので使い勝手が悪いです.
# -*- coding: utf-8 -*- require "MeCab" if __FILE__ == $0 node = MeCab::Tagger.new.parseToNode("俺、この戦争が終わったら結婚するんだ。") while node puts "#{node.surface}\t#{node.feature}" node = node.next end end
while nodeとかnode = node.nextとか,非常にRubyらしくない感じでアレですね.eachとか使いたい.(メソッド名がCamelCaseなのも非常にアレですが,mecab-rubyはSWIGでコードを自動生成しているみたいなのである程度は仕方ないのかも)
幸いなことにRubyは既存のクラスを自由に書き換えられるので(オープンクラス),以下のようにparseToNodeを再定義してNodeのArrayを返すようにすればこの問題は解決します.
# -*- coding: utf-8 -*- require "MeCab" module MeCab class Tagger # parseToNodeの別名(エイリアス)を作ってprivate化する alias_method :parseToNode_org, :parseToNode private :parseToNode_org # parseToNodeを再定義する def parseToNode(*args) #オリジナルのparseToNodeを呼び出す node = parseToNode_org(*args) # NodeのArrayを作って返す nodes = [] while node nodes.push(node) node = node.next end nodes end end end if __FILE__ == $0 nodes = MeCab::Tagger.new.parseToNode("俺、この戦争が終わったら結婚するんだ。") # Array#eachが使える! nodes.each do |node| puts "#{node.surface}\t#{node.feature}" end end
オープンクラスって素敵.
上のRubyスクリプトをMeCabの代わりにrequireするだけでNodeのArrayを返すparseToNodeが使えるようになるので,while nodeとnode = node.nextに嫌気が差したら是非試してみてください.