現在文字列の比較部分を高速化するために悩んでいます。
対象文字列、キーワード(2~40byte程度で300語句以上)ともに日本語,大文字,小文字,記号など
対象文字列の文中にキーワードがマッチングするかどうかを判定。
foreach ($keywords_array as $key => $value) {
if (stripos($title, $key)!==False) {
matching($value);
break;
}
}
対象文字列に規則性が無いので、正規表現は使えないかな?と思い
上記のようなコーディングになりましたが、何かよりよい高速化への手法があればご教授ください。
※サーバはレンタルサーバなので高速化ツールは考えておりません。
何度も同じデータに対して検索をかけるような案件であれば、データベースのようにあらかじめ
インデックスを作成しておき、部分一致ではなく、完全一致させることで高速化を狙うという
手法があります。
■コード例
//データ用意
$arr = array(
'親譲(おやゆず)りの無鉄砲(むてっぽう)で小供の時から損ばかりしている。'
, '小学校に居る時分学校の二階から飛び降りて一週間ほど腰(こし)を抜(ぬ)かした事がある。'
, 'なぜそんな無闇(むやみ)をしたと聞く人があるかも知れぬ。別段深い理由でもない。'
);
//インデックス
$idx = array(
'おやゆず' => 0
, 'むてっぽう' => 0
, 'こし' => 1
, 'ぬ' => 1
, 'むやみ' => 2
);
//---------
//処理1
//---------
$start = nowtime();
$key = 'むやみ';
for($i=0; $i<100000; $i++ )
foreach($arr as $tmp)
if(stripos($tmp, $key) !== False )
break;
echo nowtime() - $start . "\n";
//---------
//処理2
//---------
$start = nowtime();
$key = 'むやみ';
for($i=0; $i<100000; $i++ )
foreach($arr as $tmp)
if( array_key_exists($key, $idx) )
break;
echo nowtime() - $start . "\n";
//http://rikimaru-0720116.cocolog-nifty.com/blog/2008/10/php-b0c1....
function nowtime(){
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
?>
■実行結果
$php a.php
2.67902994156
0.140805959702
単語の切り出しは、形態素解析などを用いればOKかと。
レンサバの場合、入っていないことが多いと思いますので、あらかじめローカルで作成するか
Yahoo!のWebAPIを利用するなんて方法もあります。
http://developer.yahoo.co.jp/webapi/jlp/ma/v1/parse.html
もしインデックスを用いると検索性が落ちるようであれば、最初はインデックスを見に行き
そのあと全件走査するだけでも違ってきます。
※もちろん使われ方によりますが。
・インデックスの利用
・ベンチマークの手法
・単語切り出しAPI
非常にためになりました。
そして完全一致は盲点でした、対象文字に造語が多く切り出しが難しいですが
比較計測し、高速化できるパターンを組み込みたいと思います。ありがとうございます。
引き続き募集します。