ふと、「ハリー・ポッターとアズカバンの囚人」って文字があるとして、「ハリーポッター」(ナカグロなし)が含まれてるかどうかって、PHPでどうやるんだ?
という疑問が湧いたので作ってみた。
function str_in_str($source = NULL, $keyword = NULL, $encoding = NULL) {
static $splitted = array();
if (empty($source) || empty($keyword)) {
return FALSE;
}
if (empty($encoding)) {
$encoding = mb_internal_encoding();
}
if (empty($splitted[$keyword])) {
// キーワードを1文字ずつ分解
$split = array();
$len = mb_strlen($keyword, $encoding);
for ($i = 0; $i < $len; $i++) {
$split[] = mb_substr($keyword, $i, 1, $encoding);
}
$splitted[$keyword] = $split;
} else {
$split = $splitted[$keyword];
$len = count($split);
}
// 含まれている数がキーワードの文字数より少なければFALSE
if (preg_match_all('/('.implode('|', $split).')/u', $source) < $len) {
return FALSE;
}
// 一文字ずつ調べてヒットするたびに文字を削っていく。
$copy = $source;
$count = 0;
foreach($split as $val) {
$pos = mb_strpos($copy, $val, 0, $encoding);
if (false !== $pos) {
$copy = mb_substr($copy, $pos, NULL, $encoding);
++$count;
}
}
// ヒット数がキーワード文字数以上ならTRUE
return ($count >= $len);
}
以下のような結果が出た。
$word = 'ハリーポッター'; // これが含まれるか調べたい
str_in_str('ハリー・ポッターとアズカバンの囚人', $word); // TRUE
str_in_str('はりもぐハーリー', $word); // FALSE
str_in_str('ポリー・ハッターと謎のプリン', $word); // FALSE
str_in_str('ハリーポのツイッター', $word); // TRUE ヒットしてしまう・・・
結果、辞書でもない限り確実なのは無理なので、どうでもいいプロジェクト向け。