leepowers
leepowers

Reputation: 38318

PHP case-insensitive in_array function

Is it possible to do case-insensitive comparison when using the in_array function?

So with a source array like this:

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

The following lookups would all return true:

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

What function or set of functions would do the same? I don't think in_array itself can do this.

Upvotes: 167

Views: 141613

Answers (13)

Michael
Michael

Reputation: 9293

Although this question is 14 years old - I have an answer that's an actual answer and not a new ramshackle function.

The problem is that the in_array function is case sensitive - and there isn't any way to change that - so don't try. You could upper or lowercase everything - but where's the fun in that? There are a ton of other PHP array functions we can choose from, surely we can do the same thing if given the right function and parameters.

That function is...

array_uintersect - computes the intersection of arrays, compares data by callback.

The first trick is to give an array as the needle, which is easy enough - by simply surrounding the search string with square braces. Next, we pass the comparison array - self-explanatory. Finally, the third parameter is the callback function, in this case "strcasecmp" (case-insensitive string comparison). To make it behave like in_array - we cast the result as a bool.

$needle = "abc";
$haystack = ["Abc","deF","gHi"];
$result = (bool)array_uintersect([$needle],$haystack,"strcasecmp");

In this case, $result = true;

A clever person might realize that if you don't cast as a bool, the haystack is placed first, and the needle array second - your result will contain the cased match from the haystack instead of the lowercased needle.

$result = array_uintersect($haystack,[$needle],"strcasecmp");
print_r($result);
Array
(
    [0] => "Abc"
)

Upvotes: 1

user1077915
user1077915

Reputation: 894

  • in_array accepts these parameters : in_array(search,array,type)
  • if the search parameter is a string and the type parameter is set to TRUE, the search is case-sensitive.
  • so in order to make the search ignore the case, it would be enough to use it like this :
$a = array( 'one', 'two', 'three', 'four' );
$b = in_array( 'ONE', $a, false );

Upvotes: -3

will
will

Reputation: 149

Why not use a regex case insensitive search - this will ignore the case in both the haystack and the needle:

$haystack = array('MacKnight', 'MacManus', 'MacManUS', 'MacMurray');
$needle='MacMANUS';
$regex='/'.$needle.'/i';
$matches  = preg_grep ($regex, $haystack);
if($m=current($matches)){ // find first case insensitive match
   echo 'match found: '.$m;
}else{
   echo 'no match found.';
} 

Upvotes: 0

AVe
AVe

Reputation: 1307

$user_agent = 'yandeX';
$bots = ['Google','Yahoo','Yandex'];        
        
foreach($bots as $b){
     if( stripos( $user_agent, $b ) !== false ) return $b;
}

Upvotes: 0

cletus
cletus

Reputation: 625485

The obvious thing to do is just convert the search term to lowercase:

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

of course if there are uppercase letters in the array you'll need to do this first:

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

and search that. There's no point in doing strtolower on the whole array with every search.

Searching arrays however is linear. If you have a large array or you're going to do this a lot, it would be better to put the search terms in key of the array as this will be much faster access:

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

then

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

The only issue here is that array keys must be unique so if you have a collision (eg "One" and "one") you will lose all but one.

Upvotes: 298

Carlos Coelho
Carlos Coelho

Reputation: 41

/**
 * 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);

}

Upvotes: 2

Mike Q
Mike Q

Reputation: 7357

Say you want to use the in_array, here is how you can make the search case insensitive.

Case insensitive in_array():

foreach($searchKey as $key => $subkey) {

     if (in_array(strtolower($subkey), array_map("strtolower", $subarray)))
     {
        echo "found";
     }

}

Normal case sensitive:

foreach($searchKey as $key => $subkey) {

if (in_array("$subkey", $subarray))

     {
        echo "found";
     }

}

Upvotes: 11

Tyler Carter
Tyler Carter

Reputation: 61597

function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

From Documentation

Upvotes: 143

TURTLE
TURTLE

Reputation: 3847

I wrote a simple function to check for a insensitive value in an array the code is below.

function:

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

how to use:

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

Upvotes: 1

Alex
Alex

Reputation: 81

The above is correct if we assume that arrays can contain only strings, but arrays can contain other arrays as well. Also in_array() function can accept an array for $needle, so strtolower($needle) is not going to work if $needle is an array and array_map('strtolower', $haystack) is not going to work if $haystack contains other arrays, but will result in "PHP warning: strtolower() expects parameter 1 to be string, array given".

Example:

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

So i created a helper class with the releveant methods, to make case-sensitive and case-insensitive in_array() checks. I am also using mb_strtolower() instead of strtolower(), so other encodings can be used. Here's the code:

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;
    }
}
}

Upvotes: 3

omer
omer

Reputation: 1

$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);

Upvotes: 0

ghostdog74
ghostdog74

Reputation: 343201

you can use preg_grep():

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

print_r( preg_grep( "/ONe/i" , $a ) );

Upvotes: 116

Gazler
Gazler

Reputation: 84190

function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Source: php.net in_array manual page.

Upvotes: 57

Related Questions