【问题标题】:PHP case-insensitive in_array functionPHP 不区分大小写的 in_array 函数
【发布时间】:2011-01-11 02:40:19
【问题描述】:

使用in_array函数时是否可以进行不区分大小写的比较?

所以使用这样的源数组:

$a= array(
 'one',
 'two',
 'three',
 'four'
);

以下查找都将返回 true:

in_array('one', $a);
in_array('two', $a);
in_array('ONE', $a);
in_array('fOUr', $a);

什么功能或一组功能会做同样的事情?我不认为in_array 本身可以做到这一点。

【问题讨论】:

    标签: php arrays


    【解决方案1】:
    $user_agent = 'yandeX';
    $bots = ['Google','Yahoo','Yandex'];        
            
    foreach($bots as $b){
         if( stripos( $user_agent, $b ) !== false ) return $b;
    }
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    【解决方案2】:

    显而易见的事情就是将搜索词转换为小写:

    if (in_array(strtolower($word), $array)) { 
      ...
    

    当然,如果数组中有大写字母,您首先需要这样做:

    $search_array = array_map('strtolower', $array);
    

    然后搜索。每次搜索都对整个数组执行 strtolower 是没有意义的。

    然而,搜索数组是线性的。如果您有一个大数组或者您要经常这样做,最好将搜索词放在数组的键中,因为这将更快更快地访问:

    $search_array = array_combine(array_map('strtolower', $a), $a);
    

    然后

    if ($search_array[strtolower($word)]) { 
      ...
    

    这里唯一的问题是数组键必须是唯一的,因此如果发生冲突(例如“一”和“一”),您将丢失除一个之外的所有键。

    【讨论】:

    • 这应该是公认的答案。添加正则表达式有时只会产生 2 个问题。
    • 这里的array_flip 不是比array_combine 更快的解决方案吗? $search_array = array_flip(array_map('strtolower', $a));
    • 一行:in_array(strtolower($word), array_map('strtolower', $array))
    • @Akira Yamamoto - "fix syntax" edit 是怎么回事?我们不允许在这里修复代码。我把它回滚了。
    【解决方案3】:
    /**
     * in_array function variant that performs case-insensitive comparison when needle is a string.
     *
     * @param mixed $needle
     * @param array $haystack
     * @param bool $strict
     *
     * @return bool
     */
    function in_arrayi($needle, array $haystack, bool $strict = false): bool
    {
    
        if (is_string($needle)) {
    
            $needle = strtolower($needle);
    
            foreach ($haystack as $value) {
    
                if (is_string($value)) {
                    if (strtolower($value) === $needle) {
                        return true;
                    }
                }
    
            }
    
            return false;
    
        }
    
        return in_array($needle, $haystack, $strict);
    
    }
    
    
    /**
     * in_array function variant that performs case-insensitive comparison when needle is a string.
     * Multibyte version.
     *
     * @param mixed $needle
     * @param array $haystack
     * @param bool $strict
     * @param string|null $encoding
     *
     * @return bool
     */
    function mb_in_arrayi($needle, array $haystack, bool $strict = false, ?string $encoding = null): bool
    {
    
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
    
        if (is_string($needle)) {
    
            $needle = mb_strtolower($needle, $encoding);
    
            foreach ($haystack as $value) {
    
                if (is_string($value)) {
                    if (mb_strtolower($value, $encoding) === $needle) {
                        return true;
                    }
                }
    
            }
    
            return false;
    
        }
    
        return in_array($needle, $haystack, $strict);
    
    }
    

    【讨论】:

    • 最后。花了 8 年时间才有人站出来提供最有效的技术 -- 早期的return。当只需要找到1个针时,找到后继续迭代是没有意义的。我会修正一个错字,加入 $strict 概念并进行一些改进,也许接近 3v4l.org/WCTi2 。这篇文章并不完美,但它的核心是正确的。
    【解决方案4】:
    • in_array 接受这些参数:in_array(search,array,type)
    • 如果搜索参数是字符串且类型参数设置为 TRUE,则搜索区分大小写。
    • 所以为了让搜索忽略大小写,像这样使用它就足够了:

    $a = array('一', '二', '三', '四');

    $b = in_array('ONE', $a, false);

    【讨论】:

    【解决方案5】:

    假设您要使用 in_array,以下是如何使搜索不区分大小写。

    in_array() 不区分大小写:

    foreach($searchKey as $key => $subkey) {
    
         if (in_array(strtolower($subkey), array_map("strtolower", $subarray)))
         {
            echo "found";
         }
    
    }
    

    区分大小写:

    foreach($searchKey as $key => $subkey) {
    
    if (in_array("$subkey", $subarray))
    
         {
            echo "found";
         }
    
    }
    

    【讨论】:

      【解决方案6】:
      function in_arrayi($needle, $haystack) {
          return in_array(strtolower($needle), array_map('strtolower', $haystack));
      }
      

      来自Documentation

      【讨论】:

      • 你应该阻止引用你从其他地方获得的代码(或任何真正的东西)。
      • 只是为了清楚。这不是批评。只是一个建议(只有我的意见,没有任何官方意见)。 :) 至少如果我从页面复制代码 sn-p 我会阻止引用它。
      • 另外,使用代码块可以更好地描述它,因为它是“代码”。块引用它不允许它被正确格式化。
      • 我已经更正了,在使用实际按钮将> 添加到每一行后,它可以工作。我只是习惯于手动将> 放在第一行。
      • 我习惯用 ctrl-Q 来做。这与代码块有一个问题,因为出于某种原因它会换行。不要问我为什么。但是您可以更正它或在每行的开头手动添加>
      【解决方案7】:

      我编写了一个简单的函数来检查数组中的不敏感值,代码如下。

      功能:

      function in_array_insensitive($needle, $haystack) {
         $needle = strtolower($needle);
         foreach($haystack as $k => $v) {
            $haystack[$k] = strtolower($v);
         }
         return in_array($needle, $haystack);
      }
      

      使用方法:

      $array = array('one', 'two', 'three', 'four');
      var_dump(in_array_insensitive('fOUr', $array));
      

      【讨论】:

        【解决方案8】:

        如果我们假设数组只能包含字符串,那么以上是正确的,但数组也可以包含其他数组。 in_array() 函数也可以接受 $needle 的数组,因此如果 $needle 是数组,则 strtolower($needle) 不起作用,如果 $haystack 包含其他数组,则 array_map('strtolower', $haystack) 不起作用数组,但会导致“PHP 警告:strtolower() 期望参数 1 为字符串,给定数组”。

        例子:

        $needle = array('p', 'H');
        $haystack = array(array('p', 'H'), 'U');
        

        所以我创建了一个具有相关方法的帮助类,以进行区分大小写和不区分大小写的 in_array() 检查。我也在使用 mb_strtolower() 而不是 strtolower(),所以可以使用其他编码。代码如下:

        class StringHelper {
        
        public static function toLower($string, $encoding = 'UTF-8')
        {
            return mb_strtolower($string, $encoding);
        }
        
        /**
         * Digs into all levels of an array and converts all string values to lowercase
         */
        public static function arrayToLower($array)
        {
            foreach ($array as &$value) {
                switch (true) {
                    case is_string($value):
                        $value = self::toLower($value);
                        break;
                    case is_array($value):
                        $value = self::arrayToLower($value);
                        break;
                }
            }
            return $array;
        }
        
        /**
         * Works like the built-in PHP in_array() function — Checks if a value exists in an array, but
         * gives the option to choose how the comparison is done - case-sensitive or case-insensitive
         */
        public static function inArray($needle, $haystack, $case = 'case-sensitive', $strict = false)
        {
            switch ($case) {
                default:
                case 'case-sensitive':
                case 'cs':
                    return in_array($needle, $haystack, $strict);
                    break;
                case 'case-insensitive':
                case 'ci':
                    if (is_array($needle)) {
                        return in_array(self::arrayToLower($needle), self::arrayToLower($haystack), $strict);
                    } else {
                        return in_array(self::toLower($needle), self::arrayToLower($haystack), $strict);
                    }
                    break;
            }
        }
        }
        

        【讨论】:

          【解决方案9】:
          $a = [1 => 'funny', 3 => 'meshgaat', 15 => 'obi', 2 => 'OMER'];  
          
          $b = 'omer';
          
          function checkArr($x,$array)
          {
              $arr = array_values($array);
              $arrlength = count($arr);
              $z = strtolower($x);
          
              for ($i = 0; $i < $arrlength; $i++) {
                  if ($z == strtolower($arr[$i])) {
                      echo "yes";
                  }  
              } 
          };
          
          checkArr($b, $a);
          

          【讨论】:

          • 请添加您提出的解决方案的描述。
          【解决方案10】:

          你可以使用preg_grep():

          $a= array(
           'one',
           'two',
           'three',
           'four'
          );
          
          print_r( preg_grep( "/ONe/i" , $a ) );
          

          【讨论】:

          • 使用正则表达式不是一个好的解决方案,因为它可能很慢......也许 array_map 更快
          • 为了使其成为 in_array 的替代品,返回一个布尔值,它变为:count(preg_grep('/^'.preg_quote($needle).'/$',$a)&gt;0)。那就不那么优雅了。 (注意 ^ 和 $ 字符是必需的,除非需要部分匹配。)但是,如果您确实想要返回匹配的条目,我喜欢这个解决方案。
          • 最后一条注释包含语法错误:/$ 应该是 $/。
          • @DarrenCook 据我所知,bool cast 也可以作为空数组工作 (bool)preg_grep('/^'.preg_quote($needle).'$/',$a)将转换为 false
          • 似乎更简单的方法是转换为小写。
          【解决方案11】:
          function in_arrayi($needle, $haystack) {
              return in_array(strtolower($needle), array_map('strtolower', $haystack));
          }
          

          来源:php.net in_array manual page.

          【讨论】:

          • 如果你知道数组中有什么,你可以省略array_map;但这是一个很好的例子。
          • 我确实做到了。因为在每次调用时映射数组是非常可笑的。
          • 另外,假设(如 Chacha)这直接来自文档,最好阻止引用它。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-19
          • 1970-01-01
          相关资源
          最近更新 更多