在strpos中使用数组作为指针


89

strpos搜索字符串时,如何使用针阵列?例如:

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

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

因为当使用它时,它将不起作用,如果有这样的东西,那会很好

Answers:


134

@Dave来自http://www.php.net/manual/zh/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,您建议使用什么工具?
Binyamin

5
我不确定,但是也许我们可以从$ offset处推进字符串,并在找到第一个针头时停止。考虑一个充满“ a”的大文本。取$ needles = [a,b]。您的函数strposa将遍历所有文本,但这不是必需的!我可以理解吗?
Arnaud 2013年

感谢@Arnaud提供的功能建议!我完全同意您的建议的重要性,并使用改进的代码示例更新了我的答案。
Binyamin

这并不是我想说的,因为新功能$ needles = [b,a]仍然存在问题,此外该功能不再返回第一次出现的位置。让我解释一下。假设字符串是“ ABCDEF”,并且针是C和F。我们所能做的就是遍历字符串:A,B ... C!我们检测到C,因此我们在这里停止,我们可以返回第一次出现的needle的位置,即2。它可以与多个单字符字符串一起使用,但是我没有考虑确切的实现。
Arnaud

1
我通过更改改进了代码foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; },因此它返回了匹配项的密钥以进行进一步处理。
詹姆斯·卡梅隆

51

str_replace相当快。

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

语法错误:#​​3行上的1个右括号过多(由于> 6个字符的编辑要求,我无法在上面的代码中直接更正它;))
richey

1
糟糕,没有袖手旁观。立即修复。振作起来!
莱昂

6
最好的解决方案之一!
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。除非将标志设置为true后立即中断。然后必须将标志解释为警告“大海捞针不在”。这意味着您要实现的目标是检查所有的针头都在干草堆中。这不是问题。嗯是的。!==假
Kevin Gagnon

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"在此页面上尝试一些。


因为我正在查看数组中包含子字符串,所以这对我来说非常理想。我免于编写像“%$ string%”这样的sql命令
Maurice Elagu '17

4

此表达式搜索所有字母:

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


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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.