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

MacMac
źródło

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
Binyamin
źródło
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);
Leon
źródło
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 
Dave
źródło
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.

Evan Mulawski
źródło
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
}
netcoder
źródło
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.

Jonas Lundman
źródło
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)
mario
źródło
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;
}
Rajnesh Nadan
źródło
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!';
}
Jedyny ChemistryBlob
źródło
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.

billynoah
źródło
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.

hakre
źródło
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));
ConorReidd
źródło
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;
}
Obliczanie CO4
źródło
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;
}
Andy Nguyen
źródło