Використання масиву як голок у strpos


91

Як ви використовуєте strposдля масиву голок при пошуку рядка? Наприклад:

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

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

Оскільки, використовуючи це, це не буде працювати, було б добре, якби було щось подібне

Відповіді:


138

@ Створіть оновлений фрагмент з 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);
}

Як користуватись:

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

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

повернеться trueчерез array "cheese".

Оновлення: Покращений код із зупинкою при знаходженні першої з голок:

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, що ви пропонуєте реалізувати?
Біньямін,

5
Я не впевнений, але, можливо, ми могли б просунутися в рядку від $ offset і зупинитися, коли буде знайдена перша з голок. Подумайте про великий текст, повний "а". Візьміть $ голки = [a, b]. Ваша функція strposaбуде проходити через весь текст, але це не обов'язково! Я зрозумілий?
Arnaud

Дякую @Arnaud за пропозицію функції! Я повністю погоджуюсь з вашими пропозиціями і оновив свою відповідь вдосконаленим прикладом коду.
Біньямін,

Це не зовсім те, що я хотів сказати, оскільки з вашою новою функцією $ Needles = [b, a] ще є проблема, і крім того, функція більше не повертає позицію першого входження. Дозвольте мені пояснити ще трохи. Припустимо, що рядок "ABCDEF", а голки - C і F. Що б ми могли зробити, це пропустити через рядок: A, B ... C! Ми виявляємо C, тому зупиняємось тут і можемо повернути положення першого входження голки, яке дорівнює 2. Це може працювати з більш ніж односимвольними рядками, але я не думав про точну реалізацію.
Arnaud

1
Я вдосконалив код, змінивши foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, тому він повертає ключ відповідного елемента для подальшої обробки.
Джеймс Кемерон,

53

str_replace значно швидший.

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

синтаксична помилка: занадто багато закриваючої дужки в рядку # 3 (я не зміг це виправити безпосередньо у коді вище через вимогу редагування> 6 символів;))
Річі

1
На жаль, це було з манжети. Виправлено зараз. Вітаємо за голови!
Леон,

7
одне з найкращих рішень!
andys

18

У наведеному нижче коді не тільки показано, як це зробити, але й додано його до зручної функції, що рухається вперед. Його написала "jesda". (Я знайшов його в Інтернеті)

Код 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;
}
?>

Використання:

$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 

Я вважаю, що це повертає лише першу позицію, яку він знаходить. Будь-які пропозиції щодо того, як його налаштувати, щоб повернути положення кожної голки в копиці сіна?
Chaya Cooper

7

Ви можете переглядати масив і встановлювати значення "прапор", якщо strposповертається false.

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

Потім перевірте значення $flag.


6
не повинно бути !== flase?
Joe Huang

Має бути! == false. Якщо ви не зламаєтеся відразу після того, як встановите прапор на істину. І тоді довелося б тлумачити прапор як Попередження про те, що голки немає в копиці сіна. Це означає, що ви намагаєтесь досягти, це перевірити, чи всі ваші голки знаходяться в копиці сіна. Яке питання не в цьому. Отже .. так. ! == false
Кевін Ганьон

5

Якщо ви просто хочете перевірити, чи певні символи насправді є в рядку чи ні, використовуйте strtok :

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

Неймовірна відповідь - НАБАГАТО швидше виконання, ніж кілька strpos (), наприклад, if (strpos ($ string, "a")! == false && strpos ($ string, "c")! == false && strpos ($ string, " d ")! == false)
Єдиний і хімічний

5

Питання, наведений приклад - це просто «приклад» чи саме те, що ви шукаєте? Тут є багато різнобічних відповідей, і я не розумію складності прийнятої.

Щоб з’ясувати, чи в рядку існує БУДЬ-який вміст масиву голок , і швидко повернути true чи false:

$string = 'abcdefg';

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

Якщо так, будь ласка, дайте @Leon кредит за це.

Щоб з’ясувати, чи ВСІ значення масиву голок існують у рядку, як у цьому випадку, усі три 'a', 'b'та 'c'ПОВИННІ бути присутніми, як ви називаєте своїм "наприклад"

echo 'Усі літери знайдені в рядку!';

Багато відповідей тут виходять за рамки цього контексту, але я сумніваюся, що зміст питання, яке ви позначили як вирішене. Наприклад, прийнята відповідь - це голка

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

Що робити, якщо всі ці слова ПОВИННІ бути знайдені в рядку?

Тоді ви спробуєте кілька "not accepted answers"на цій сторінці.


Це ідеально для мене спрацювало, оскільки я шукав, що мій масив містить підряди. Мене врятували від написання команди sql на кшталт "% $ string%"
Моріс Елагу,

4

Цей вираз шукає всі літери:

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

3

Ви можете спробувати це:

function in_array_strpos($word, $array){

foreach($array as $a){

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

return false;
}

1

Ви також можете спробувати використовувати strpbrk () для заперечення (жодна буква не знайдена):

$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

Це мій підхід. Ітерація над символами у рядку, доки не буде знайдено збіг. На більшому наборі голок це перевершить прийняту відповідь, оскільки не потрібно перевіряти кожну голку, щоб визначити, чи знайдено збіг.

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

Я порівняв це з прийнятою відповіддю, і з масивом більше 7 $needlesце було значно швидше.


0

З таким кодом:

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

Потім перевірте значення $flag. Якщо це так true, усі листи знайдено. Якщо ні, то це false.


0

Я пишу нову відповідь, яка, сподіваюся, допоможе кожному, хто шукає подібного до того, що я є.

Це працює у випадку з "У мене є кілька голок, і я намагаюся використовувати їх, щоб знайти виділений рядок". і це питання я зіткнувся, щоб знайти це.

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

Масив $foundбуде містити список усіх відповідних голок, елементом масиву з найбільшим значенням підрахунку буде рядок (и), який ви шукаєте, ви можете отримати це за допомогою:

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

0

Відповідь на @binyamin та @Timo .. (недостатньо балів, щоб додати коментар ..), але результат не містить позиції ..
Наведений нижче код поверне фактичну позицію першого елемента, для чого призначений strpos робити. Це корисно, якщо ви очікуєте знайти рівно 1 збіг. Якщо ви розраховуєте знайти кілька збігів, то позиція першого знайденого може бути безглуздою.

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

Просто оновлення зверху відповідей

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.