Używanie tablicy jako igieł w strpos


91

Jak używać strpostablicy igieł podczas wyszukiwania łańcucha? Na przykład:

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

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

Ponieważ przy użyciu tego nie zadziała, byłoby dobrze, gdyby było coś takiego

Odpowiedzi:


138

@Dave zaktualizowany fragment z 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);
}

Jak używać:

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

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

powróci z truepowodu array "cheese".

Aktualizacja: Ulepszony kod z zatrzymaniem po znalezieniu pierwszej z igieł:

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, jakie jest twoje sugerowane narzędzie?
Binyamin,

5
Nie jestem pewien, ale może moglibyśmy przesunąć ciąg z przesunięcia $ i zatrzymać się, gdy zostanie znaleziona pierwsza z igieł. Pomyśl o dużym tekście pełnym „a”. Weź $ igieł = [a, b]. Twoja funkcja strposaprzejdzie przez cały tekst, ale nie jest to konieczne! Czy jestem zrozumiały?
Arnaud,

Dzięki @Arnaud za sugestię funkcji! Całkowicie zgadzam się z ważnością Twojej sugestii i zaktualizowałem moją odpowiedź o ulepszony przykład kodu.
Binyamin,

Nie jest to dokładnie to, co chciałem powiedzieć, ponieważ z nową funkcją $ needles = [b, a] ma jeszcze problem, a ponadto funkcja nie zwraca już pozycji pierwszego wystąpienia. Pozwólcie, że wyjaśnię trochę więcej. Załóżmy, że struna to „ABCDEF”, a igły to C i F. To, co moglibyśmy zrobić, to przebiec przez strunę: A, B ... C! Wykrywamy C, więc zatrzymujemy się w tym miejscu i możemy zwrócić pozycję pierwszego wystąpienia igły, czyli 2. Może to działać z więcej niż jednoznakowymi łańcuchami, ale nie myślałem o dokładnej implementacji.
Arnaud,

1
Poprawiłem kod, zmieniając go foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, więc zwraca klucz pasującego elementu do dalszej obsługi.
James Cameron,

53

str_replace jest znacznie szybszy.

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

błąd składni: 1 nawias zamykający za dużo w linii nr 3 (nie mogłem tego poprawić bezpośrednio w powyższym kodzie ze względu na wymóg edycji> 6 znaków;))
richey

1
Ups, to było bez mankietu. Naprawiono teraz. Pozdrawiamy za heads up!
Leon

7
jedno z najlepszych rozwiązań!
andys

18

Poniższy kod nie tylko pokazuje, jak to zrobić, ale także umieszcza go w łatwej w użyciu funkcji posuwającej się naprzód. Został napisany przez „jesdę”. (Znalazłem to online)

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

Stosowanie:

$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 

Uważam, że zwraca to tylko 1. znalezioną pozycję. Jakieś sugestie, jak go dostosować, aby przywrócić pozycję każdej igły w stogu siana?
Chaya Cooper

7

Możesz iterować po tablicy i ustawić wartość „flagi”, jeśli strposzwraca false.

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

Następnie sprawdź wartość $flag.


6
nie powinno być !== flase?
Joe Huang

Powinno być! == false. Chyba że złamiesz zaraz po ustawieniu flagi na true. A potem musiałby zinterpretować flagę jako Ostrzeżenie, że w stogu siana nie ma igły. Oznacza to, że to, co próbujesz osiągnąć, to sprawdzić, czy wszystkie twoje igły są w stogu siana. Nie o to chodzi. Więc tak. ! == false
Kevin Gagnon

5

Jeśli chcesz tylko sprawdzić, czy określone znaki są rzeczywiście w ciągu, czy nie, użyj strtok :

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

Niesamowita odpowiedź - DUŻO szybsze wykonanie niż wiele strpos (), np. If (strpos ($ string, "a")! == false && strpos ($ string, "c")! == false && strpos ($ string, " d ")! == false)
The One and Only ChemistryBlob

5

Pytanie, czy podany przykład to tylko „przykład”, czy dokładnie to, czego szukasz? Jest tu wiele mieszanych odpowiedzi i nie rozumiem złożoności przyjętej.

Aby dowiedzieć się, czy JAKIEKOLWIEK zawartość tablicy igieł istnieje w ciągu znaków i szybko zwrócić prawdę lub fałsz:

$string = 'abcdefg';

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

Jeśli tak, daj za to kredyt @Leon .

Aby dowiedzieć się, czy WSZYSTKIE wartości tablicy igieł istnieją w ciągu, tak jak w tym przypadku, wszystkie trzy 'a', 'b'i 'c'MUSZĄ być obecne, tak jak wspominasz jako „na przykład”

echo 'Wszystkie litery znajdują się w ciągu!';

Wiele odpowiedzi tutaj jest poza tym kontekstem, ale wątpię, czy intencja pytania, którą określiłeś jako rozwiązana. Np. Zaakceptowaną odpowiedzią jest igła

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

A jeśli wszystkie te słowa MUSZĄ znajdować się w ciągu?

Następnie wypróbuj kilka "not accepted answers"na tej stronie.


To działało idealnie dla mnie, ponieważ szukałem mojej tablicy zawierającej podciągi. Uratowano mnie przed pisaniem polecenia sql, takiego jak „% $ string%”
Maurice Elagu

4

To wyrażenie wyszukuje wszystkie litery:

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

3

Możesz spróbować tego:

function in_array_strpos($word, $array){

foreach($array as $a){

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

return false;
}

1

Możesz także spróbować użyć strpbrk () do negacji (żadna z liter nie została znaleziona):

$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

To jest moje podejście. Iteruj po znakach w ciągu, aż zostanie znalezione dopasowanie. W przypadku większej liczby igieł będzie to lepsze od zaakceptowanej odpowiedzi, ponieważ nie trzeba sprawdzać każdej igły, aby stwierdzić, że znaleziono dopasowanie.

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

Porównałem to z zaakceptowaną odpowiedzią i przy tablicy ponad 7 $needlesbyło to znacznie szybsze.


0

Z następującym kodem:

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

Następnie sprawdź wartość $flag. Jeśli tak true, wszystkie litery zostały znalezione. Jeśli nie, to jest false.


0

Piszę nową odpowiedź, która, mam nadzieję, pomoże każdemu, kto szuka czegoś podobnego do tego, kim jestem.

Działa to w przypadku „Mam wiele igieł i próbuję ich użyć, aby znaleźć wyodrębniony sznurek”. i to jest pytanie, na które natknąłem się, aby je znaleźć.

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

Tablica $foundbędzie zawierała listę wszystkich pasujących igieł, element tablicy o najwyższej wartości licznika będzie ciągiem, którego szukasz, możesz to uzyskać za pomocą:

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

0

Odpowiedz na @binyamin i @Timo .. (za mało punktów, aby dodać komentarz ...), ale wynik nie zawiera pozycji ..
Poniższy kod zwróci rzeczywistą pozycję pierwszego elementu, do której ma służyć strpos zrobić. Jest to przydatne, jeśli spodziewasz się znaleźć dokładnie 1 dopasowanie. Jeśli spodziewasz się znaleźć wiele dopasowań, pozycja pierwszego znalezionego może być bez znaczenia.

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

Tylko aktualizacja z powyższych odpowiedzi

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;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.