Utiliser un tableau comme aiguilles dans les strpos


89

Comment utilisez-vous le strpospour un tableau d'aiguilles lors de la recherche d'une chaîne? Par exemple:

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';

if(strpos($string, $find_letters) !== false)
{
    echo 'All the letters are found in the string!';
}

Parce que lors de l'utilisation de ceci, cela ne fonctionnerait pas, ce serait bien s'il y avait quelque chose comme ça

Réponses:


135

@Dave un extrait de code mis à jour de http://www.php.net/manual/en/function.strpos.php#107351

function strposa($haystack, $needles=array(), $offset=0) {
        $chr = array();
        foreach($needles as $needle) {
                $res = strpos($haystack, $needle, $offset);
                if ($res !== false) $chr[$needle] = $res;
        }
        if(empty($chr)) return false;
        return min($chr);
}

Comment utiliser:

$string = 'Whis string contains word "cheese" and "tea".';
$array  = array('burger', 'melon', 'cheese', 'milk');

if (strposa($string, $array, 1)) {
    echo 'true';
} else {
    echo 'false';
}

reviendra true, à cause de array "cheese".

Mise à jour: code amélioré avec arrêt lorsque la première des aiguilles est trouvée:

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
        if(strpos($haystack, $query, $offset) !== false) return true; // stop on first true result
    }
    return false;
}
$string = 'Whis string contains word "cheese" and "tea".';
$array  = array('burger', 'melon', 'cheese', 'milk');
var_dump(strposa($string, $array)); // will return true, since "cheese" has been found

1
@Arnaud, quel est votre outil suggéré?
Binyamin

5
Je ne suis pas sûr, mais peut-être que nous pourrions avancer dans la chaîne à partir de $ offset et s'arrêter lorsque la première des aiguilles est trouvée. Pensez à un gros texte rempli de "a". Prenez $ aiguilles = [a, b]. Votre fonction strposaparcourra tout le texte, mais ce n'est pas nécessaire! Suis-je compréhensible?
Arnaud

Merci @Arnaud pour la suggestion de fonctionnalité! Je suis totalement d'accord avec l'importance de votre suggestion et j'ai mis à jour ma réponse avec un exemple de code amélioré.
Binyamin

Ce n'est pas exactement ce que je voulais dire, car avec votre nouvelle fonction $ aiguilles = [b, a] a encore un problème, et en plus la fonction ne retourne plus la position de la première occurrence. Laissez-moi vous expliquer un peu plus. Supposons que la chaîne est "ABCDEF" et que les aiguilles sont C et F. Ce que nous pourrions faire est de parcourir la chaîne: A, B ... C! Nous détectons C, donc nous nous arrêtons ici et nous pouvons retourner la position de la première occurrence d'une aiguille, qui est 2. Cela pourrait fonctionner avec plus que des chaînes à un seul caractère, mais je n'ai pas pensé à l'implémentation exacte.
Arnaud

1
J'ai amélioré le code en le changeant foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, il renvoie donc la clé de l'élément correspondant pour une manipulation ultérieure.
James Cameron

51

str_replace est considérablement plus rapide.

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
$match = (str_replace($find_letters, '', $string) != $string);

erreur de syntaxe: 1 crochet fermant trop à la ligne 3 (je n'ai pas pu le corriger directement dans le code ci-dessus en raison de l'exigence de modification de> 6 caractères;))
richey

1
Oups, c'était improvisé. Corrigé maintenant. Vive la tête!
Leon

6
l'une des meilleures solutions!
andys

18

Le code ci-dessous montre non seulement comment le faire, mais le met également dans une fonction facile à utiliser pour aller de l'avant. Il a été écrit par "jesda". (Je l'ai trouvé en ligne)

Code PHP:

<?php
/* strpos that takes an array of values to match against a string
 * note the stupid argument order (to match strpos)
 */
function strpos_arr($haystack, $needle) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $what) {
        if(($pos = strpos($haystack, $what))!==false) return $pos;
    }
    return false;
}
?>

Usage:

$needle = array('something','nothing');
$haystack = "This is something";
echo strpos_arr($haystack, $needle); // Will echo True

$haystack = "This isn't anything";
echo strpos_arr($haystack, $needle); // Will echo False 

Je crois que cela ne renvoie que la 1ère position qu'il trouve. Des suggestions sur la façon de le modifier pour rétablir la position de chaque aiguille dans la botte de foin?
Chaya Cooper le

7

Vous pouvez parcourir le tableau et définir une valeur "flag" si strposretourne false.

$flag = false;
foreach ($find_letters as $letter)
{
    if (strpos($string, $letter) === false)
    {
        $flag = true;
    }
}

Vérifiez ensuite la valeur de $flag.


6
ça ne devrait pas être !== flase?
Joe Huang

Cela devrait être! == false. À moins que vous ne rompiez juste après avoir défini votre drapeau sur vrai. Et puis devrait interpréter le drapeau comme un avertissement qu'une aiguille n'est pas dans la botte de foin. Cela signifie que ce que vous essayez de faire est de vérifier que toutes vos aiguilles sont dans la botte de foin. Ce n'est pas la question. Donc voilà. ! == false
Kevin Gagnon

5

Si vous voulez juste vérifier si certains caractères sont réellement dans la chaîne ou non, utilisez strtok :

$string = 'abcdefg';
if (strtok($string, 'acd') === $string) {
    // not found
} else {
    // found
}

Réponse incroyable - Exécution BEAUCOUP plus rapide que plusieurs strpos (), par exemple, if (strpos ($ string, "a")! == false && strpos ($ string, "c")! == false && strpos ($ string, " d ")! == false)
The One and Only ChemistryBlob

5

La question, est-ce que l'exemple fourni est juste un "exemple" ou exactement ce que vous recherchez? Il y a beaucoup de réponses mitigées ici, et je ne comprends pas la complexité de la réponse acceptée.

Pour savoir si N'IMPORTE QUEL contenu du tableau d'aiguilles existe dans la chaîne et renvoyer rapidement true ou false:

$string = 'abcdefg';

if(str_replace(array('a', 'c', 'd'), '', $string) != $string){
    echo 'at least one of the needles where found';
};

Si oui, veuillez donner @Leon .

Pour savoir si TOUTES les valeurs du tableau d'aiguilles existent dans la chaîne, comme dans ce cas, les trois 'a', 'b'et 'c'DOIVENT être présentes, comme vous le mentionnez comme "par exemple"

echo 'Toutes les lettres se trouvent dans la chaîne!';

Beaucoup de réponses ici sont hors de ce contexte, mais je doute que l'intension de la question que vous avez marquée comme résolue. Par exemple, la réponse acceptée est une aiguille de

$array  = array('burger', 'melon', 'cheese', 'milk');

Et si tous ces mots DOIVENT être trouvés dans la chaîne?

Ensuite, vous en essayez "not accepted answers"sur cette page.


Cela a parfaitement fonctionné pour moi car je cherchais mon tableau contenait des sous-chaînes. J'ai été sauvé de l'écriture d'une commande SQL comme "% $ string%"
Maurice Elagu

4

Cette expression recherche toutes les lettres:

count(array_filter( 
    array_map("strpos", array_fill(0, count($letters), $str), $letters),
"is_int")) == count($letters)

3

Vous pouvez essayer ceci:

function in_array_strpos($word, $array){

foreach($array as $a){

    if (strpos($word,$a) !== false) {
        return true;
    }
}

return false;
}

1

Vous pouvez également essayer d'utiliser strpbrk () pour la négation (aucune des lettres n'a été trouvée):

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';

if(strpbrk($string, implode($find_letters)) === false)
{
    echo 'None of these letters are found in the string!';
}

1

Telle est ma démarche. Itérez les caractères de la chaîne jusqu'à ce qu'une correspondance soit trouvée. Sur un plus grand nombre d'aiguilles, cela surpassera la réponse acceptée car il n'est pas nécessaire de vérifier chaque aiguille pour déterminer qu'une correspondance a été trouvée.

function strpos_array($haystack, $needles = [], $offset = 0) {
    for ($i = $offset, $len = strlen($haystack); $i < $len; $i++){
        if (in_array($haystack[$i],$needles)) {
            return $i;
        }
    }
    return false;
}

J'ai comparé cela à la réponse acceptée et avec un tableau de plus de 7, $needlesc'était considérablement plus rapide.


0

Avec le code suivant:

$flag = true;
foreach($find_letters as $letter)
    if(false===strpos($string, $letter)) {
        $flag = false; 
        break;
    }

Vérifiez ensuite la valeur de $flag. Si c'est le cas true, toutes les lettres ont été trouvées. Sinon, c'est false.


0

J'écris une nouvelle réponse qui, espérons-le, aidera tous ceux qui recherchent des choses similaires à ce que je suis.

Cela fonctionne dans le cas de "J'ai plusieurs aiguilles et j'essaye de les utiliser pour trouver une chaîne de caractères". et c'est la question que j'ai rencontrée pour trouver cela.

    $i = 0;
    $found = array();
    while ($i < count($needle)) {
        $x = 0;
        while ($x < count($haystack)) {
            if (strpos($haystack[$x], $needle[$i]) !== false) {
                array_push($found, $haystack[$x]);
            }
            $x++;
        }
        $i++;
    }

    $found = array_count_values($found);

Le tableau $foundcontiendra une liste de toutes les aiguilles correspondantes, l'élément du tableau avec la valeur de comptage la plus élevée sera la ou les chaînes que vous recherchez, vous pouvez l'obtenir avec:

print_r(array_search(max($found), $found));

0

Répondez à @binyamin et @Timo .. (pas assez de points pour ajouter un commentaire ..) mais le résultat ne contient pas la position ..
Le code ci-dessous retournera la position réelle du premier élément à laquelle strpos est destiné faire. Ceci est utile si vous prévoyez de trouver exactement 1 correspondance. Si vous prévoyez de trouver plusieurs correspondances, la position du premier trouvé peut être sans signification.

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
      $res=strpos($haystack, $query, $offset);
      if($res !== false) return $res; // stop on first true result
    }
    return false;
}

0

Juste une mise à niveau des réponses ci-dessus

function strsearch($findme, $source){
    if(is_array($findme)){
        if(str_replace($findme, '', $source) != $source){
            return true;
        }
    }else{
        if(strpos($source,$findme)){
            return true;
        }
    }
    return false;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.