24

2つの重要な違いがあるstrpos()のような関数を探しています。

  1. 複数の針を受け入れることができるようにするため。私は1つで何千もの針を意味します。
  2. 干し草の山の中の針のすべての出現を検索し、開始位置の配列を返すため。

もちろん、それはすべての針をループするだけでなく、効率的な解決策でなければなりません。私はこのフォーラムを検索しましたが、次のような同様の質問がありました。

しかし、それらのネザーは私が探していたものでした。私は自分の質問をよりよく説明するためにstrposを使用しています。おそらく、この目的のためにまったく異なるものを使用する必要があります。

私はZend_Search_Luceneを知っていますが、これを実現するために使用できるかどうか、そしてどのように(一般的な考え方)に興味がありますか?

あなたの助けと時間をどうもありがとう!

4

6 に答える 6

9

複数のプレグマッチを試す

if (preg_match('/word|word2/i', $str))

複数の strpos 値のチェック

于 2016-01-14T19:32:55.740 に答える
7

私の戦略のサンプルコードは次のとおりです。

function strpos_array($haystack, $needles, $offset=0) {
    $matches = array();

    //Avoid the obvious: when haystack or needles are empty, return no matches
    if(empty($needles) || empty($haystack)) {
        return $matches;
    }

    $haystack = (string)$haystack; //Pre-cast non-string haystacks
    $haylen = strlen($haystack);

    //Allow negative (from end of haystack) offsets
    if($offset < 0) {
        $offset += $heylen;
    }

    //Use strpos if there is no array or only one needle
    if(!is_array($needles)) {
        $needles = array($needles);
    }

    $needles = array_unique($needles); //Not necessary if you are sure all needles are unique

    //Precalculate needle lengths to save time
    foreach($needles as &$origNeedle) {
        $origNeedle = array((string)$origNeedle, strlen($origNeedle));
    }

    //Find matches
    for(; $offset < $haylen; $offset++) {
        foreach($needles as $needle) {
            list($needle, $length) = $needle;
            if($needle == substr($haystack, $offset, $length)) {
                $matches[] = $offset;
                break;
            }
        }
    }

    return($matches);
}

上記の単純な力ずくの方法を実装しました。これは、針と干し草の山 (言葉だけでなく) の任意の組み合わせで機能します。おそらくより高速なアルゴリズムについては、以下を確認してください。


その他の解決策

function strpos_array($haystack, $needles, $theOffset=0) {
    $matches = array();

    if(empty($haystack) || empty($needles)) {
        return $matches;
    }

    $haylen = strlen($haystack);

    if($theOffset < 0) {  // Support negative offsets
        $theOffest += $haylen;
    }

    foreach($needles as $needle) {
        $needlelen = strlen($needle);
        $offset = $theOffset;

        while(($match = strpos($haystack, $needle, $offset)) !== false) {
            $matches[] = $match;
            $offset = $match + $needlelen;
            if($offset >= $haylen) {
                break;
            }
        }
    }

    return $matches;
}
于 2011-08-01T09:56:56.510 に答える
2

これがOPの質問に答えないことは知っていますが、このページは複数の針を持つstrposのGoogleのトップにあるため、コメントしたかった. これを行うための簡単な解決策があります(繰り返しますが、これはOPの質問に固有のものではありません-申し訳ありません):

    $img_formats = array('.jpg','.png');
    $missing = array();
    foreach ( $img_formats as $format )
        if ( stripos($post['timer_background_image'], $format) === false ) $missing[] = $format;
    if (count($missing) == 2)
        return array("save_data"=>$post,"error"=>array("message"=>"The background image must be in a .jpg or .png format.","field"=>"timer_background_image"));

$missing 配列に 2 つの項目が追加された場合、入力が $img_formats 配列のどの画像フォーマットも満たしていないことを意味します。その時点で、エラーなどを返すことができることがわかります。これは簡単に小さな関数に変換できます。

    function m_stripos( $haystack = null, $needles = array() ){
        //return early if missing arguments 
        if ( !$needles || !$haystack ) return false; 
        // create an array to evaluate at the end
        $missing = array(); 
        //Loop through needles array, and add to $missing array if not satisfied
        foreach ( $needles as $needle )
            if ( stripos($haystack, $needle) === false ) $missing[] = $needle;
        //If the count of $missing and $needles is equal, we know there were no matches, return false..
        if (count($missing) == count($needles)) return false; 
        //If we're here, be happy, return true...
        return true;
    }

代わりに then 関数を使用した最初の例に戻ります。

    $needles = array('.jpg','.png');
    if ( !m_strpos( $post['timer_background_image'], $needles ) )
        return array("save_data"=>$post,"error"=>array("message"=>"The background image must be in a .jpg or .png format.","field"=>"timer_background_image"));

もちろん、関数が true または false を返した後に何をするかはあなた次第です。

于 2013-04-29T09:42:24.593 に答える
1

単語全体を検索しているようです。この場合、このようなものが役立つかもしれません。組み込み関数を使用するため、カスタム コードよりも高速である必要がありますが、プロファイルを作成する必要があります。

$words = str_word_count($str, 2);

$word_position_map = array();

foreach($words as $position => $word) {
    if(!isset($word_position_map[$word])) {
        $word_position_map[$word] = array();
    }
    $word_position_map[$word][] = $position;
}

// assuming $needles is an array of words
$result = array_intersect_key($word_position_map, array_flip($needles));

情報 (針など) を正しい形式で保存すると、実行時間が改善されます (たとえば、 を呼び出す必要がないためarray_flip)。

str_word_countドキュメントからのメモ:

この関数の目的のために、'word' は、アルファベット文字を含むロケール依存の文字列として定義されます。この文字列には、"'" および "-" 文字を含めることはできますが、先頭を文字にすることはできません。

そのため、ロケールを正しく設定してください。

于 2011-08-01T10:21:55.497 に答える
0

正規表現を使用できます。OR 演算がサポートされています。ただし、これは strpos に比べてかなり遅くなります。

于 2011-08-01T09:42:01.543 に答える