MapReduce::LiteによるWordCount
http://codezine.jp/article/detail/2485
こちらのサイトで紹介されているHadoopのサンプルプログラム
WordCount(WordCount.java)と同じ事を行なうものを、
MapReduce::Liteで書いてみた。
WordCountはスペース区切りで並べられた単語を数えるプログラムである。
入力データ:
hoge hoge hoge fuga fuga hoge uho
出力データ:
uho => 1
fuga => 2
hoge => 4
まずマップを記述する。
package WordCount::Mapper; use Moose; with 'MapReduce::Lite::Mapper'; sub map { my ($self, $key, $value) = @_; my @elements = split /\s+/, $value; for my $element (@elements) { $self->emit($element, 1); } }
MapReduce::Lite::Mapperを継承し、新たにWordCount::Mapperを作成する。
map関数をオーバライドして、スペース区切りのデータを切り分け、
それぞれの単語を「<単語, 1>」の形でemitするようにする。
この後、reducerに渡される前にシャッフルという段階があり、処理される。
この処理が行なわれた後、リストは各単語毎に「<単語, (1, 1, ...)>」という形になる。
次にこのリストを受け取るReducerを作成する。
package WordCount::Reducer; use Moose; with 'MapReduce::Lite::Reducer'; sub reduce { my ($self, $key, $value) = @_; $self->emit($key, $value->size); }
MapReduce::Lite::Reducerを継承し、新たにWordCount::Reducerを作成する。
reduce関数をオーバライドして、「<単語、(1, 1, ....)>」の形で渡ってくるリストを受け取り、
(1, 1, ...)の部分の長さを求めるようにする。
実質、(1, 1, ...)の長さは、単語の出現回数となる。
これらのMapReduceを実行するプログラムは下記の通り。
package main; use FindBin::lib; use MapReduce::Lite; my $spec = MapReduce::Lite::Spec->new(intermidate_dir => "./tmp"); for (@ARGV) { my $in = $spec->create_input; $in->file($_); $in->mapper('WordCount::Mapper'); } $spec->out->reducer('WordCount::Reducer'); $spec->out->num_tasks(1); mapreduce($spec);
中間ファイルを置くディレクトリ「tmp」を作成し、単語リストが書かれたファイル「./inputs/file1」を読み込ませて、プログラムを実行。
$ mkdir tmp
$ ./WordCount.pl ./inputs/file1
uho => 1
fuga => 2
hoge => 4