回答編集履歴

1 渡しますじゃなくて返りますでしょ。

raccy

raccy score 20904

2016/01/11 08:11  投稿

ちょっと色々ありますが、私の手元でとりあえず動くようになった版を貼り付けます。
```Ruby
require 'mecab'
module TFIDF
 extend self
 @@nat = MeCab::Tagger.new
 def cnt(documents)
   word_hash = {}
   terms_count = 0
   documents.each do |e|
     node = @@nat.parseToNode(e)
     while node = node.next
       if node.feature =~ /^(?:名詞,固有名詞|名詞,一般)/
         # 固有名詞と一般名詞のみ抽出
         word_hash[node.surface] ||= 0
         word_hash[node.surface] += 1
         terms_count += 1
       end
     end
   end
   word_hash.each { |key, value| word_hash[key] = value.to_f / terms_count }
   word_hash
 end
end
```
###解説
環境は、Mac OS X 10.11.2 + Ruby 2.3.0p0 に下記で入れています。
```Terminal
brew install mecab
brew install mecab-ipadic
gem install mecab
```
* `require "MeCab"`じゃなくて`require "mecab"`
私の環境(Mac OS X)だと"mecab"でした。Windowsだったら大文字小文字を無視するのでうまく言っているかでかも知れません。
* `pares`じゃなくて`parseToNode`
`MeCab::Tagger#parse`は解析した言葉全てを改行("\n")区切りで一つの文字列で渡します。`do...end`とかは対応していません。`parse`の文字列をsplitで分割してeachしてもいいのですが、`MeCab::Tagger#parseToNode`で`MeCab::Node`を取得した方がいいでしょう。`MeCab::Node#surface`でその言葉を、`MeCab::Node#feature`でCSVになっている部分を取得できます。
`MeCab::Tagger#parse`は解析した言葉全てを改行("\n")区切りで一つの文字列で返ります。`do...end`とかは対応していません。`parse`の文字列をsplitで分割してeachしてもいいのですが、`MeCab::Tagger#parseToNode`で`MeCab::Node`を取得した方がいいでしょう。`MeCab::Node#surface`でその言葉を、`MeCab::Node#feature`でCSVになっている部分を取得できます。
この`MeCab::Node`ですが、非常にRubyっぽくありません。
1. `parseToNode`で取得されるのは**文頭**という特殊なノードです。文頭なので、surfaceは""(空文字)です。
2. 次のノードは`MeCab::Node#next`で取得します。最後だとnilが返るようです。
このことから、下記のように最初の1つは飛ばして、whileで次々に入れていけばうまくいきます。
```Ruby
node = @@nat.parseToNode(e)
while node = node.next
 # ここに各nodeに対する処理を書く
end
```
* if の分岐は冗長すぎない?
`node.feature`に対して固有名詞か一般名詞かをみるだけでいいと思います。記号が入ることはあり得ないです(そんなのがあったら、MeCabのバグでしょ、たぶん)し、長さがないこともあり得ない(そんなのがあったら、これもMeCabのバグでしょ、たぶん)ので、条件は一つだけでいいと思います。先頭の"^"を使い、"(?:...)"を使ってちょっとだけ高速になったような気がします。たぶん。
###おまけ。
[mecab-ext](https://github.com/taiki45/mecab-ext)というもっとRubyっぽくMeCabを操作できるGemがあるようです。こっちを使ってもいいかもしれません。
参考: [Qiita: Mecab をもっと手軽に Ruby で扱える Gem](http://qiita.com/taiki45/items/774b114917002994bf4e)

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る