strpos () avec plusieurs aiguilles?

je cherche une fonction comme strpos () avec deux différences significatives:

  1. pour pouvoir accepter plusieurs aiguilles. Je veux dire des milliers d'aiguilles à une.
  2. pour rechercher toutes les occurrences des aiguilles dans la botte de foin et pour retourner une rangée de positions de départ.

bien sûr, il doit être une solution efficace pas seulement une boucle à travers chaque aiguille. J'ai cherché par le biais de ce forum et il y avait des questions similaires à celle-ci, comme:

mais au-dessous d'eux était ce que je cherche. J'utilise strpos juste pour illustrer ma question mieux, probablement quelque chose de totalement différent doit être utilisé à cette fin.

je suis au courant de Zend_Search_Lucene et je suis intéressé si elle peut être utilisée pour atteindre CE et comment (juste l'idée générale)?

Merci beaucoup pour votre aide et du temps!

21
demandé sur Community 2011-08-01 13:38:41

5 réponses

voici un exemple de code pour ma stratégie:

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);
}

j'ai mis en place une méthode de force brute simple ci-dessus qui fonctionnera avec n'importe quelle combinaison d'aiguilles et de meules de foin (pas seulement des mots). Pour des algorithmes plus rapides, consultez:


Autre Solution

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;
}
7
répondu Bailey Parker 2011-08-01 13:25:46

essayer preg match pour plusieurs

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

vérification de plusieurs valeurs strpos

5
répondu user3270784 2017-05-23 12:09:42

je sais que cela ne répond pas à la question de L'OP, mais je voulais faire un commentaire puisque cette page est en haut de Google pour strpos avec des aiguilles multiples. Voici une solution simple pour le faire (encore une fois, ce n'est pas spécifique à la question de L'OP - désolé):

    $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"));

si 2 éléments sont ajoutés au tableau $missing ce qui signifie que l'entrée ne satisfait aucun des formats d'image dans le tableau $img_formats. À ce point, vous savez que vous pouvez retourner une erreur, etc. Cela pourrait se transforme facilement en une petite fonction:

    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;
    }

retour à notre premier exemple en utilisant alors la fonction à la place:

    $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"));

bien sûr, ce que vous faites après le retour de la fonction vrai ou faux dépend de vous.

2
répondu FueledPublishing 2013-04-29 10:12:53

il semble que vous cherchiez mots entiers . Dans ce cas, quelque chose comme ça pourrait aider. Comme il utilise des fonctions intégrées, il devrait être plus rapide que le code personnalisé, mais vous avez le profil:

$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));

stocker les informations ( comme les aiguilles) dans le bon format améliorera la durée d'exécution (par exemple, comme vous n'avez pas à appeler array_flip ).

Note du str_word_count document:

aux fins de cette fonction, "word" est défini comme une chaîne dépendante d'une locale contenant des caractères alphabétiques, qui peuvent également contenir, mais pas commencer par "'" et " - " caractères.

alors assurez-vous de régler la locale correctement.

1
répondu Felix Kling 2011-08-01 10:27:24

vous pouvez utiliser une expression régulière, ils soutiennent ou des opérations. Cela le rendrait cependant assez lent, par rapport à strpos.

0
répondu TJHeuvel 2011-08-01 09:42:01