strpos () avec plusieurs aiguilles?
je cherche une fonction comme strpos () avec deux différences significatives:
- pour pouvoir accepter plusieurs aiguilles. Je veux dire des milliers d'aiguilles à une.
- 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:
- utilisant un réseau comme aiguilles dans strpos
- définir aiguilles multiples à l'aide de bandes
- ne Pouvez pas rechercher un tableau en PHP in_array pour la présence de plusieurs aiguilles
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!
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;
}
essayer preg match pour plusieurs
if (preg_match('/word|word2/i', $str))
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.
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.
vous pouvez utiliser une expression régulière, ils soutiennent ou des opérations. Cela le rendrait cependant assez lent, par rapport à strpos.