【问题标题】:PHP stripos not returning all positionsPHP stripos 不返回所有位置
【发布时间】:2017-12-03 02:01:43
【问题描述】:

我将返回所有与stripos 函数匹配的数组

$requestedservice = request('service');
$result_array = array_filter($allservicesname, function($item) use ($requestedservice) {
return (stripos($item, $requestedservice) !== false);
        });

这只适用于第一次出现,例如,如果干草堆是Walk dance and rock,如果针是Walk,它会返回Walk dance and rock,但如果针是Walk rock,它不会返回Walk dance and rock。为什么会这样?

有没有办法找到所有出现的事件,以便将干草堆Walk dance and rock 与针Walk rock 匹配?

如果针是Walk run,它不应该匹配Walk dance and rock,这是一种正常的用例

【问题讨论】:

  • 一切都按预期工作。您需要为每个可能或可能不会被其他单词/字符分隔的单词调用一个单独的stripos()。也许您想使用像 preg_grep() 这样的正则表达式解决方案
  • 正如 php man 所说: stripos — 查找字符串中不区分大小写的子字符串的第一次出现的位置。所以你不能用这个函数找到多次出现。针“走岩”。不是“Walk dance rock”的子字符串,正如@mickmackusa 所说,您可能需要使用正则表达式
  • @Riccardo 将walk rock 放入walk dance rock 的任何其他解决方案
  • php.net/manual/it/function.preg-match.php 这应该可以完成这项工作

标签: php strpos


【解决方案1】:

看来您将能够通过不区分大小写的关键字检查循环来实现所需的过滤。

代码:(Demo)

$allservicesname=['dance','Walk rock','Walk dance and rock','Walk'];  // array of haystacks

$requestedservice='walk rock';  // string of needles

$result_array=array_filter($allservicesname,function($string)use($requestedservice){
    foreach(explode(' ',$requestedservice) as $keyword){
        if(stripos($string,$keyword)===false){
            return false;
        }
    }
    return true;
});

var_export($result_array);

输出:

array (
  1 => 'Walk rock',
  2 => 'Walk dance and rock',
)

请注意,原始键保留在输出数组中。另外,我应该提一下,关键字可以以任何顺序出现并保持准确性。


或者,如果您没有被正则表达式的想法吓到,preg_grep() 可以简洁地执行此任务。该函数旨在对每个元素使用正则表达式过滤数组。

代码:(Demo) (Regex Pattern Demo)

$allservicesname=['Walk dance and rock walk','dance','walk','rock and walk','sidewalk and rockwall'];  // array of haystacks

$requestedservice='walk rock';  // string of needles
$pattern='/(?=.*\Q'.str_replace(' ','\E)(?=.*\Q',$requestedservice).'\E)/i';  // with literal substring matching, no wordboundaries
//$pattern='/(?=.*\b\Q'.str_replace(' ','\E\b)(?=.*\b\Q',$requestedservice).'\E\b)/i';  // with wordboundaries  
echo $pattern,"\n";

$result_array=preg_grep($pattern,$allservicesname);

var_export($result_array);

输出:

/(?=.*\Qwalk\E)(?=.*\Qrock\E)/i
array (
  0 => 'Walk dance and rock walk',
  3 => 'rock and walk',
  4 => 'sidewalk and rockwall',
)

如果您不希望元素 [4] 符合条件,则字边界是必要的 - 改用第二个(已注释掉的)模式声明。

\Q..\E 确保正则表达式中具有特殊含义的字符不会干扰执行。其中的子字符串被解释为“字面意思”。

【讨论】:

  • 请解释一下这是怎么可能的,因为我的演示链接证明了他们的成功。您可以向我发布一个演示链接,其中包含破坏我的方法的示例数据吗?我会解决的。
  • 谢谢。这对我有用。但我遇到的唯一问题是,它与 &' 这样的特殊字符不匹配,我该如何匹配?
  • 我们在讨论处理 html 实体时的匹配失败 (",',&,<,>) 吗?听起来像是 php.net/manual/en/function.html-entity-decode.php 的工作如果这不能解决您的问题,请给我发送一个演示链接(就像我在我的答案中包含的那样),它可以重现问题,我会调查它。
  • 它匹配 walk - rockwalk rock 但不匹配 walk - rockwalk - rock 我也尝试使用 htmlentitydecode,可能是什么问题
  • 请在演示链接中给我你的确切代码,我会修复它。
【解决方案2】:

正如其他人提到的,stripos 只返回第一次出现。使用explode 将字符串转换为数组后,您可以使用foreach 循环和in_array 来完成您要查找的内容。

这是行动:

$all_services = explode(" ", "walk dance and rock");
$requested_services = explode(" ", "walk rock");
$result_array = array();

foreach ($all_services as $service) {
    if (in_array($service, $requested_services)) {
        $result_array[] = $service;
    }
}

【讨论】:

    猜你喜欢
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2022-06-12
    • 2018-10-05
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多