168

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.

14 Answers 14

299

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.

Sign up to request clarification or add additional context in comments.

6 Comments

This should be the accepted answer. Adding regular expressions sometimes just makes 2 problems.
Wouldn't array_flip here be an even faster solution, instead of array_combine? $search_array = array_flip(array_map('strtolower', $a));
one line: in_array(strtolower($word), array_map('strtolower', $array))
@Akira Yamamoto - what's with the "fix syntax" edit? We're not allowed to fix code here. I rolled it back.
|
143
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

From Documentation

7 Comments

You should blockquote code (or anything really) you get from somewhere else.
Just to be clear. It's not a criticism. Just a suggestion (and only my opinion, nothing official). :) At least if I copy a code snippet from a page I'll block quote it.
Plus, using a code block better describes it, as it is 'code'. Block quoting it does not allow for it to be properly formatted.
I stand corrected, after using the actual button to add > to every line, it works. I am just used to manually putting the > at the first line.
I'm used to using ctrl-Q to do it. That has one problem with code blocks because for some reason it wraps lines. Don't ask me why. But you can just either correct that or manually put a > at the start of each line.
|
117

you can use preg_grep():

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

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

10 Comments

using regular expressions isn't a good solution, because it can be slow... maybe array_map is faster
To make it a drop-in replacement for in_array, returning a bool, it becomes: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). Not so elegant, then. (Notice the ^ and $ characters are required, unless partial matching is desired.) However if you actually want the matching entries returned, I like this solution.
The last comment contains a syntax error: /$ should be $/ instead.
@DarrenCook as far as i know a bool cast would also work (bool)preg_grep('/^'.preg_quote($needle).'$/',$a), as an empty array would cast to false
Seems like the easier way to go is to just convert to lowercase.
|
57
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Source: php.net in_array manual page.

3 Comments

If you know what is in the array, you can leave out the array_map; but this is a good example.
I did actually. Because mapping the array on every call is, well, ludicrous.
Also, assuming (like Chacha) this comes direct from the docs, it's better to block quote it.
11

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

}

Comments

3

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

Comments

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

}

1 Comment

Finally. It took 8 years before someone stepped up and provided the most efficient technique -- an early return. When only needing to find 1 of the needle, it is pointless to keep iterating after finding it. I would fix a typo, bake in the $strict concept and make some refinements though, perhaps something close to 3v4l.org/WCTi2 . This post isn't perfect, but its heart is in the right place.
1

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

Comments

1

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;

As one cleverly 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"
)

2 Comments

This is okay if you want to find ALL matches, it is inefficient if you just want to find one. array_#intersect() will unnecessarily process the entire array.
@mickmackusa - I can't disagree. The 2nd use case is what I was searching for when I found this. I realized that casting it as a bool solved the original question, so I posted it. I hope it helps someone. I thought it was heroically terse.
1

The most efficient and elegant functional-style approach was born in PHP8.4. Use array_any() or array_all() to make case-insensitive comparisons between the needle and the array values until the short-circuiting condition is found. Demo

echo array_all(
         $haystack,
         fn($hay) => strcasecmp($hay, $needle)
     ) ? 'missing' : 'found'

This is equivalent: Demo

echo array_any(
         $haystack,
         fn($hay) => !strcasecmp($hay, $needle)
     ) ? 'found' : 'missed';

Comments

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

1 Comment

Please, add a descriptioin of the solution you are proposing.
0
$user_agent = 'yandeX';
$bots = ['Google','Yahoo','Yandex'];        
        
foreach($bots as $b){
     if( stripos( $user_agent, $b ) !== false ) return $b;
}

1 Comment

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
0

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

Comments

-4
  • 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 );

1 Comment

The third parameter controls whether or not the type of the variable is checked, not the case. When true strict type comparisons will be used, e.g. '1' !== 1. When false type juggling will be used, e.g. '1' == 1. See php.net/in_array and php.net/manual/en/types.comparisons.php for documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.