Использование массива в качестве иголок в 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!';
}

Потому что при использовании этого не сработало бы, было бы хорошо, если бы было что-то вроде этого

MacMac
источник

Ответы:

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
@ Арно, что вы предлагаете?
Биньямин
5
Я не уверен, но, возможно, мы могли бы продвинуться по строке от $ offset и остановиться, когда будет найдена первая игла. Подумайте о большом тексте, полном «а». Возьмите $ Needles = [a, b]. Ваша функция strposaбудет проходить через весь текст, но это не обязательно! Я вас понял?
Арно
Спасибо @Arnaud за предложение функции! Я полностью согласен с важностью вашего предложения и обновил свой ответ улучшенным примером кода.
Биньямин
Это не совсем то, что я хотел сказать, потому что с вашей новой функцией $ Needles = [b, a] все еще есть проблема, и, кроме того, функция больше не возвращает позицию первого вхождения. Позвольте мне объяснить еще немного. Предположим, что строка - это «ABCDEF», а иглы - это C и F. Что мы могли сделать, так это пройти через строку: A, B ... C! Мы обнаруживаем C, поэтому мы останавливаемся на этом и можем вернуть позицию первого появления стрелки, которая равна 2. Он может работать с более чем односимвольными строками, но я не думал о точной реализации.
Арно
1
Я улучшил код, изменив его foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, так что он возвращает ключ соответствующего элемента для дальнейшей обработки.
Джеймс Кэмерон
54

str_replace значительно быстрее.

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
$match = (str_replace($find_letters, '', $string) != $string);
Леон
источник
синтаксическая ошибка: слишком много закрывающей скобки в строке # 3 (я не смог исправить это прямо в приведенном выше коде из-за требования редактирования> 6 символов;))
richey
1
Ой, это было не так. Исправлено сейчас. Приветствую вас!
Леон
8
одно из лучших решений!
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?
Джо Хуанг
Должно быть! == false. Если только вы не сломаетесь сразу после того, как установите свой флаг в значение true. А затем пришлось бы интерпретировать флаг как предупреждение о том, что иголки нет в стоге сена. Это означает, что вы пытаетесь проверить, все ли ваши иголки в стоге сена. Вопрос не в этом. Так что да. ! == 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)
The One and Only ChemistryBlob
5

Возникает вопрос, является ли предоставленный пример просто «примером» или именно тем, что вы ищете? Здесь много смешанных ответов, и я не понимаю сложности принятого.

Чтобы узнать, существует ли ЛЮБОЕ содержимое массива игл в строке, и быстро вернуть истину или ложь:

$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.

hakre
источник
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 делать. Это полезно, если вы ожидаете найти ровно одно совпадение. Если вы ожидаете найти несколько совпадений, то позиция первого найденного может быть бессмысленной.

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;
}
CO4 вычисления
источник
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;
}
Энди Нгуен
источник