Usare un array come aghi in strpos


89

Come si usa strposper una serie di aghi durante la ricerca di una corda? Per esempio:

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

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

Perché quando lo usi, non funzionerebbe, sarebbe bello se ci fosse qualcosa di simile

Risposte:


134

@Dave uno snippet aggiornato da 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);
}

Come usare:

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

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

tornerà true, a causa di array "cheese".

Aggiornamento: codice migliorato con arresto quando viene trovato il primo degli aghi:

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, qual è il tuo attrezzo suggerito?
Binyamin

5
Non ne sono sicuro, ma forse potremmo avanzare nella stringa da $ offset e fermarci quando viene trovato il primo degli aghi. Pensa a un grande testo pieno di "a". Prendi $ aghi = [a, b]. La tua funzione strposaeseguirà tutto il testo, ma non è necessario! Sono comprensibile?
Arnaud

Grazie @Arnaud per il suggerimento sulla funzione! Sono totalmente d'accordo con l'importanza del tuo suggerimento e ho aggiornato la mia risposta con un esempio di codice migliorato.
Binyamin

Non è esattamente quello che volevo dire, perché con la tua nuova funzione $ needles = [b, a] ha ancora un problema, e inoltre la funzione non restituisce più la posizione della prima occorrenza. Lasciami spiegare un po 'di più. Supponiamo che la stringa sia "ABCDEF" e gli aghi siano C e F. Quello che potremmo fare è scorrere la stringa: A, B ... C! Rileviamo C, quindi ci fermiamo qui e possiamo restituire la posizione della prima occorrenza di un ago, che è 2. Potrebbe funzionare con più di stringhe a carattere singolo, ma non ho pensato all'implementazione esatta.
Arnaud

1
Ho migliorato il codice modificandolo foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, quindi restituisce la chiave dell'elemento corrispondente per un'ulteriore gestione.
James Cameron

51

str_replace è notevolmente più veloce.

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

errore di sintassi: 1 parentesi graffa di chiusura troppo alla riga # 3 (non sono riuscito a correggerlo direttamente nel codice sopra a causa del requisito di modifica di> 6 caratteri;))
richey

1
Oops, era improvvisato. Risolto ora. Grazie per l'avviso!
Leon

6
una delle migliori soluzioni!
andys

18

Il codice seguente non solo mostra come farlo, ma lo mette anche in una funzione facile da usare andando avanti. È stato scritto da "jesda". (L'ho trovato online)

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

Utilizzo:

$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 

Credo che questo restituisca solo la prima posizione che trova. Qualche suggerimento su come modificarlo per restituire la posizione di ogni ago nel pagliaio?
Chaya Cooper,

7

È possibile scorrere l'array e impostare un valore "flag" se strposrestituito false.

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

Quindi controlla il valore di $flag.


6
non dovrebbe essere !== flase?
Joe Huang

Dovrebbe essere! == false. A meno che non ti rompa subito dopo aver impostato la tua bandiera su vero. E poi avrebbe dovuto interpretare la bandiera come un Avvertimento che un ago non è nel pagliaio. Ciò significa che ciò che stai cercando di ottenere è controllare che tutti i tuoi aghi siano nel pagliaio. Quale non è la domanda. Quindi .. sì. ! == false
Kevin Gagnon

5

Se vuoi solo controllare se alcuni caratteri sono effettivamente nella stringa o meno, usa strtok :

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

Risposta incredibile: esecuzione MOLTO più veloce rispetto a più strpos (), ad esempio if (strpos ($ string, "a")! == false && strpos ($ string, "c")! == false && strpos ($ string, " d ")! == false)
The One and Only ChemistryBlob

5

La domanda, l'esempio fornito è solo un "esempio" o esattamente quello che stai cercando? Ci sono molte risposte contrastanti qui, e non capisco la complessità di quella accettata.

Per scoprire se QUALSIASI contenuto della matrice di aghi esiste nella stringa e restituire rapidamente vero o falso:

$string = 'abcdefg';

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

In tal caso, si prega di dare credito a @Leon per questo.

Per scoprire se TUTTI i valori della matrice di aghi esistono nella stringa, come in questo caso, tutti 'a', 'b'e tre e 'c'DEVONO essere presenti, come citi come "ad esempio"

echo 'Tutte le lettere si trovano nella stringa!';

Molte risposte qui sono fuori da quel contesto, ma dubito che l'intenzione della domanda come hai contrassegnato come risolta. Ad esempio, la risposta accettata è un ago di

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

E se tutte quelle parole DEVONO essere trovate nella stringa?

Quindi provane alcuni "not accepted answers"su questa pagina.


Questo ha funzionato perfettamente per me poiché stavo cercando che il mio array contenesse sottostringhe. Sono stato salvato dalla scrittura del comando sql come "% $ string%"
Maurice Elagu

4

Questa espressione cerca tutte le lettere:

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

3

Puoi provare questo:

function in_array_strpos($word, $array){

foreach($array as $a){

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

return false;
}

1

Puoi anche provare a usare strpbrk () per la negazione (nessuna delle lettere è stata trovata):

$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

Questo è il mio approccio. Ripeti i caratteri nella stringa finché non viene trovata una corrispondenza. Su una gamma più ampia di aghi questo supererà la risposta accettata perché non è necessario controllare ogni ago per determinare che è stata trovata una corrispondenza.

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

L'ho confrontato con la risposta accettata e con un array di oltre 7 è $needlesstato notevolmente più veloce.


0

Con il seguente codice:

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

Quindi controlla il valore di $flag. Se lo è true, tutte le lettere sono state trovate. In caso contrario, lo è false.


0

Sto scrivendo una nuova risposta che si spera aiuti chiunque cerchi qualcosa di simile a quello che sono.

Questo funziona nel caso di "Ho più aghi e sto cercando di usarli per trovare una corda da selezionare". e questa è la domanda in cui mi sono imbattuto per trovarlo.

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

L'array $foundconterrà un elenco di tutti gli aghi corrispondenti, l'elemento dell'array con il valore di conteggio più alto sarà la stringa (e) che stai cercando, puoi ottenerlo con:

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

0

Rispondi a @binyamin e @Timo .. (punti insufficienti per aggiungere un commento ..) ma il risultato non contiene la posizione ..
Il codice seguente restituirà la posizione effettiva del primo elemento che è ciò a cui è destinato strpos fare. Questo è utile se ti aspetti di trovare esattamente 1 corrispondenza .. Se ti aspetti di trovare più corrispondenze, la posizione della prima trovata potrebbe non avere significato.

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

Solo un aggiornamento dalle risposte di cui sopra

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.