Dartsを試してみた

ダブル配列なTrie構造を実装するためのライブラリであるDartsを試してみました。

DartsはMeCabの作者として知られる工藤 拓氏の作品で、もともとMeCabに組み込まれていたDouble-Arrayのコード部分を、工藤氏が改めてリパッケージしてものだそうです。

なおDartsそのものはC++ライブラリなので、これを他の言語から使うにはバインディングが必要となります。perlから使うにはCPANText::Dartsというモジュールがあがっているので、これを使わせてもらいます。
なおText::Dartsは、これまた有名なid:dankogai氏の作品です。

で、これらを試してみたのですが、結論から言うと
Dartsを使うには

  1. Text::Darts 0.03は現時点でDarts0.32に対応していないっぽい。makeでコケる。なのでDarts0.31を使うべし。
  2. Dartsに付属のmkdartsは g++ -o mkdart mkdarts.cpp としてコンパイルすればOK。
  3. 対象のキーワードファイルは事前にソートしておく必要があるが、export LANG="" してからsortしないとダメ。

ということがわかりました。


1つ目のText::DartsがDarts0.32に対応していない件ですが、makeするとこんなエラーがでました。

Darts.xs:21: error: invalid conversion from `char**' to `const char**'
Darts.xs:21: error: initializing argument 2 of `int Darts::DoubleArrayImpl::build(size_t, const node_type_**, const size_t*, const array_type_*, int (*)(size_t, size_t)) [with node_type_ = char, node_u_type_ = unsigned char, array_type_ = int, array_u_type_ = unsigned int, length_func_ = Darts::Length]'

Dartsの0.32の更新履歴をチェックしてみたら「細かいコードのクリーンナップ (const をできるだけ付けるようにした) 」という記述を発見。
たぶんこの「const化」の変更によってText::Darts 0.03のXSでは対応できなくなったんではないでしょうか。

やっぱり更新履歴を表記しておくことって大事なんだな、と思いつつ、
Darts0.32対応版のText::Darts、はやくCPANに登場しないかな〜、と軽くid:dankogaiさんにONEDARIしてみる実験。

ちなみにサーバの環境は RedHat ES4, perl 5.8.8, gcc 3.4.6-3 です。


2つ目のmkdartsの件は、単純に自分でコンパイルしないとバイナリでは付属されてないよ。というだけの意味です。


3つ目のソートの件はあやうくドはまりするところだった!
LANG=ja_JP.UTF-8 にしている場合に「文字列をbyte sequenceとみたときの大小順」が異なるようです。ここのブログで一発解決でした → http://blog.livedoor.jp/imsut/archives/50129131.html

ほんと、ハマる前にググってよかった〜。


以上の点に注意すると、めでたくText::DartsからDartsが呼び出せるようになります。

ですが、perldoc Text::Dartsで例示されているのは、はてなキーワードみたいに「もとのテキストをマッチした部分だけ加工して置き換える」事例だったので、純粋に「マッチしたキーワードをピックアップしたい」場合にどうすればよいのは一瞬わからなかったんですが、下記のようなスクリプトでやりたいことはできました。

use strict;
use Text::Darts;
use LWP::Simple;

my $url = "http://hoge/index.html";
my $text = get($url);

my $data;
my $td = Text::Darts->open("keyword.idx");
$td->gsub( $text, sub { $data->{ $_[0] }++; } );

for( sort { $data->{$a} <=> $data->{$b} } keys %$data ){
    print $_, "\t", $data->{$_}, "\n";
}

gsubのところの使い方がイメージと合ってない気もするんですが、こんなんでいいのかな?
一応期待したキーワードがうまく抽出できてるし、速度面でも問題ないようです。


それにしても、こんな便利なライブラリを公開してくれている工藤さん、あとperlから便利に使えるようにしてくれているid:dankogaiさん、ご両名ともグレイト。