【问题标题】:Check if string contains a value in array [duplicate]检查字符串是否包含数组中的值[重复]
【发布时间】:2013-10-27 01:39:38
【问题描述】:

我正在尝试检测一个字符串是否包含至少一个存储在数组中的 URL。

这是我的数组:

$owned_urls = array('website1.com', 'website2.com', 'website3.com');

字符串由用户输入并通过 PHP 提交。在确认页面上,我想检查输入的 URL 是否在数组中。

我尝试了以下方法:

$string = 'my domain name is website3.com';
if (in_array($string, $owned_urls))
{
    echo "Match found"; 
    return true;
}
else
{
    echo "Match not found";
    return false;
}

无论输入什么,返回总是“未找到匹配”。

这是正确的做事方式吗?

【问题讨论】:

    标签: php arrays


    【解决方案1】:

    试试这个。

    $string = 'my domain name is website3.com';
    foreach ($owned_urls as $url) {
        //if (strstr($string, $url)) { // mine version
        if (strpos($string, $url) !== FALSE) { // Yoshi version
            echo "Match found"; 
            return true;
        }
    }
    echo "Not found!";
    return false;
    

    如果要检查不区分大小写,请使用 stristr()stripos()

    【讨论】:

    • 几乎 - 如果列表中的第一个 url 不匹配,这将回显“未找到匹配”并返回 false,即使另一个匹配。else 块的内容需要放在下面foreach 循环。
    • 感谢您发现这一点。刚刚改进了我的答案。
    • 你在 $string 之后还漏掉了一个 ")" :)
    • 来自手册:**Note**: If you only want to determine if a particular needle occurs within haystack, use the faster and less memory intensive function strpos() instead.
    • @danyo 如果用户输入像site3.com 这样的域,这将不起作用。它将匹配 mysite3.com 不应该的时候
    【解决方案2】:

    试试这个:

    $owned_urls= array('website1.com', 'website2.com', 'website3.com');
    
    $string = 'my domain name is website3.com';
    
    $url_string = end(explode(' ', $string));
    
    if (in_array($url_string,$owned_urls)){
        echo "Match found"; 
        return true;
    } else {
        echo "Match not found";
        return false;
    }
    

    - 谢谢

    【讨论】:

    • 这假定字符串由空格分隔。例如它不适用于以下字符串My url is https://website3.com
    • 甚至不适用于“我有 website3.com 域”。这假定字符串在末尾,而在处理用户提交的文本时不能这样做
    • 我同意其他两位评论者的观点,即为什么假设输入数据过多。对于研究人员来说,这不是一个很好的答案,因为它的功能范围很窄。另外,答案缺少教育解释。 “试试这个”的答案错过了教育/授权数千名研究人员的机会。
    • end 函数需要一个数组引用作为它的输入参数,最好将explode(' ', $string) 的结果分配给一个变量,然后将其输入end($yourArray)。干杯
    【解决方案3】:
    $string = 'my domain name is website3.com';
    $a = array('website1.com','website2.com','website3.com');
    
    $result = count(array_filter($a, create_function('$e','return strstr("'.$string.'", $e);')))>0; 
    var_dump($result );
    

    输出

    bool(true)
    

    【讨论】:

    • 供参考; create_function 在 PHP 7.2 中已弃用
    • 这个答案缺少教育解释。 php 手册指出,strstr() 不应用于检查字符串中是否存在字符串——出于效率原因,它建议使用strpos()count()>0 可以被删除,(bool)array_filter() 之前添加,以分别将空/非空数组转换为false/true
    【解决方案4】:
    $owned_urls= array('website1.com', 'website2.com', 'website3.com');
        $string = 'my domain name is website3.com';
        for($i=0; $i < count($owned_urls); $i++)
        {
            if(strpos($string,$owned_urls[$i]) != false)
                echo 'Found';
        }   
    

    【讨论】:

    • 这个答案缺少它的教育解释(或令人信服的陈述,为什么研究人员应该使用这种技术而不是其他技术)。循环不需要在每次迭代时检查count($owned_urls),因为计数永远不会改变。一旦找到第一个匹配项,循环应该break
    【解决方案5】:

    您正在检查整个字符串到数组值。所以输出总是false

    在这种情况下,我同时使用 array_filterstrpos

    <?php
    $urls= array('website1.com', 'website2.com', 'website3.com');
    $string = 'my domain name is website3.com';
    $check = array_filter($urls, function($url){
        global $string;
        if(strpos($string, $url))
            return true;
    });
    echo $check?"found":"not found";
    

    【讨论】:

    • global可以用use()替换。
    【解决方案6】:

    如果你的$string总是一致的(即域名always在字符串的末尾),你可以使用explode()end(),然后使用@987654325 @ 检查匹配项(@Anand Solanki 在他们的回答中指出)。

    如果没有,最好使用正则表达式从字符串中提取域,然后使用in_array() 来检查匹配项。

    $string = 'There is a url mysite3.com in this string';
    preg_match('/(?:http:\/\/)?(?:www.)?([a-z0-9-_]+\.[a-z0-9.]{2,5})/i', $string, $matches);
    
    if (empty($matches[1])) {
      // no domain name was found in $string
    } else {
      if (in_array($matches[1], $owned_urls)) {
        // exact match found
      } else {
        // exact match not found
      }
    }
    

    上面的表达式可能会改进(我对这方面不是特别了解)

    Here's a demo

    【讨论】:

    • 文字点必须以正则表达式模式转义(除非在字符类中)。 \w = [A-Za-z0-9_]preg_match() 调用本身可以放在第一个 if 内,以避免进行 empty() 函数调用。
    【解决方案7】:

    如果您只想在数组中查找字符串,这会容易得多。

    $array = ["they has mystring in it", "some", "other", "elements"];
    if (stripos(json_encode($array),'mystring') !== false) {
    echo "found mystring";
    }
    

    【讨论】:

    • 你的输入数组实际上是一个字符串。
    • 我认为这是BEST ANSWER,但由于代码中的简单错误而没有收到赞成票。 @Burgi我编辑了答案,现在它是数组,甚至更多,多个子数组,他的方法仍然很好用!!
    • 这很好用,但它并不能告诉你数组与哪个键匹配。
    • 如果您要在检查之前将数组转换为字符串,为什么不直接 implode?不使用json_encode() 的一个很好的理由是,如果您的数组中包含json_encode() 将转义或变异的字符。这种突变风险是不建议将此技术作为通用工具的充分理由。 失败演示:3v4l.org/RjPbX
    • 哈哈,我错过了这里的所有 cmets,但感谢@Sohel Ahme Mesaniya,它得到了修复。无论如何,mickmackusa 的评论非常相关。
    【解决方案8】:

    这是一个小函数,它从给定字符串的数组中搜索所有值。 我在我的网站中使用它来检查访问者 IP 是否在某些页面的允许列表中。

    function array_in_string($str, array $arr) {
        foreach($arr as $arr_value) { //start looping the array
            if (stripos($str,$arr_value) !== false) return true; //if $arr_value is found in $str return true
        }
        return false; //else return false
    }
    

    如何使用

    $owned_urls = array('website1.com', 'website2.com', 'website3.com');
    
    //this example should return FOUND
    $string = 'my domain name is website3.com';
    if (array_in_string($string, $owned_urls)) {
        echo "first: Match found<br>"; 
    }
    else {
        echo "first: Match not found<br>";
    }
    
    //this example should return NOT FOUND
    $string = 'my domain name is website4.com';
    if (array_in_string($string, $owned_urls)) {
        echo "second: Match found<br>"; 
    }
    else {
        echo "second: Match not found<br>";
    }
    

    演示:http://phpfiddle.org/lite/code/qf7j-8m09

    【讨论】:

    • 它区分大小写,对于不区分大小写的版本使用stripos
    【解决方案9】:

    带有 count 参数的简单 str_replace 可以在这里工作:

    $count = 0;
    str_replace($owned_urls, '', $string, $count);
    // if replace is successful means the array value is present(Match Found).
    if ($count > 0) {
      echo "One of Array value is present in the string.";
    }
    

    更多信息 - https://www.techpurohit.com/extended-behaviour-explode-and-strreplace-php

    【讨论】:

    • 很好,我有一个疑问..这可以很好地匹配字符串的网址......我有一个字符串 $string = 'you-are-nice'; $string2 = '你更优秀';我的 $match = 'nice';我需要匹配单词 nice ,即使我的匹配字符串是 nice 也不是 nice ...
    • @Srinivas08 考虑字边界是一个合理的考虑,但不是可以用str_replace() 实现的。
    • 开发人员不应该实施这种简洁技术的最突出的原因是因为没有办法“提前返回”。换句话说,在进行替换后,绝对没有理由继续搜索替换,因此进程应该停止——但它不能。对于寻求二进制“找到”或“未找到”结果的所有任务,不应使用此技术,因为它会进行无用的额外迭代。
    【解决方案10】:
        $message = "This is test message that contain filter world test3";
    
        $filterWords = array('test1', 'test2', 'test3');
    
        $messageAfterFilter =  str_replace($filterWords, '',$message);
    
        if( strlen($messageAfterFilter) != strlen($message) )
            echo 'message is filtered';
        else
            echo 'not filtered';
    

    【讨论】:

    • 如果打扰“通过突变检查”(我不会),那么只需使用这个较早发布的更简单的答案:stackoverflow.com/a/40543118/2943403(两个答案都效率低下,因为在找到匹配项)
    【解决方案11】:

    我认为更快的方法是使用 preg_match

    $user_input = 'Something website2.com or other';
    $owned_urls_array = array('website1.com', 'website2.com', 'website3.com');
    
    if ( preg_match('('.implode('|',$owned_urls_array).')', $user_input)){
        echo "Match found"; 
    }else{
        echo "Match not found";
    }
    

    【讨论】:

    • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请edit您的回答添加一些解释,包括您所做的假设。 ref
    • 为了更安全,点必须在模式中转义:addcslashes(implode('|', $owned_urls_array, '.'))
    • 代码更少,但绝对比 strpos 慢得多
    • Regex 在正面交锋中会比strpos() 慢。我认为将preg_ 用于此类任务的唯一原因是您是否想包含词边界以提高准确性。不要使用addcslashes() 来转义正则表达式中的特殊字符,preg_quote() 是专门为解决这种必要性而设计的。
    • 另外,捕获组在模式中是无用的。
    【解决方案12】:

    我发现这个没有运行循环又快又简单。

    $array = array("this", "that", "there", "here", "where");
    $string = "Here comes my string";
    $string2 = "I like to Move it! Move it";
    
    $newStr = str_replace($array, "", $string);
    
    if(strcmp($string, $newStr) == 0) {
        echo 'No Word Exists - Nothing got replaced in $newStr';
    } else {
        echo 'Word Exists - Some Word from array got replaced!';
    }
    
    $newStr = str_replace($array, "", $string2);
    
    if(strcmp($string2, $newStr) == 0) {
        echo 'No Word Exists - Nothing got replaced in $newStr';
    } else {
        echo 'Word Exists - Some Word from array got replaced!';
    }
    

    一点解释!

    1. $newStr替换原始字符串数组中的值创建新变量。

    2. 进行字符串比较 - 如果值为 0,则表示字符串相等且没有任何内容被替换,因此字符串中不存在数组中的值。

    3. 如果是2的反之亦然,即在进行字符串比较时,原始字符串和新字符串都不匹配,这意味着有东西被替换了,因此数组中的值存在于字符串中。

    【讨论】:

    • 如果打扰“通过突变检查”(我不会),那么只需使用这个较早发布的更简单的答案:stackoverflow.com/a/40543118/2943403(两个答案都效率低下,因为在找到匹配项)
    【解决方案13】:
      $search = "web"
        $owned_urls = array('website1.com', 'website2.com', 'website3.com');
              foreach ($owned_urls as $key => $value) {
             if (stristr($value, $search) == '') {
            //not fount
            }else{
          //found
           }
    

    这是搜索任何子字符串的最佳方法,不区分大小写且快速

    就像我的mysql一样

    例如:

    从 name = "%web%" 的表中选择 *

    【讨论】:

    • php 手册指出,strstr()(或此上下文中的stristr())不应用于确定另一个字符串中是否存在一个字符串。为此,出于效率考虑,php手册推荐strpos()/stripos()
    【解决方案14】:

    您可以使用 implode 和分隔符 | 连接数组值 然后使用 preg_match 搜索该值。

    这是我想出的解决方案...

    $emails = array('@gmail', '@hotmail', '@outlook', '@live', '@msn', '@yahoo', '@ymail', '@aol');
    $emails = implode('|', $emails);
    
    if(!preg_match("/$emails/i", $email)){
     // do something
    }
    

    【讨论】:

    • preg_match() 是内爆后搜索的不必要开销。没有理由不使用具有相同效果的stripos()。我不认可这种技术——它比它需要的工作更努力,如果$emails 字符串包含对正则表达式引擎具有特殊意义的字符,它就有可能被破坏。
    【解决方案15】:

    我想出了这个对我有用的功能,希望这对某人有帮助

    $word_list = 'word1, word2, word3, word4';
    $str = 'This string contains word1 in it';
    
    function checkStringAgainstList($str, $word_list)
    {
      $word_list = explode(', ', $word_list);
      $str = explode(' ', $str);
    
      foreach ($str as $word):
        if (in_array(strtolower($word), $word_list)) {
            return TRUE;
        }
      endforeach;
    
      return false;
    }
    

    另外,请注意,如果匹配的单词是其他单词的一部分,则使用 strpos() 的答案将返回 true。例如,如果单词列表包含 'st' 并且您的字符串包含 'street',strpos() 将返回 true

    【讨论】:

    • 这是非常低效的。 OP 不要求在空格上爆炸两个字符串。这个答案不必要地复杂,有可能破坏一个不应返回匹配但随后返回匹配的字符串,因为无序的单个子字符串都符合条件。我不推荐这种方法,因为它容易失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多