php: Array keys case *insensitive* lookup?

You could use ArrayAccess interface to create a class that works with array syntax.

Example

$lower_array_object = new CaseInsensitiveArray;
$lower_array_object["thisISaKEY"] = "value";
print $lower_array_object["THISisAkey"]; //prints "value"

or

$lower_array_object = new CaseInsensitiveArray(
    array( "SoMeThInG" => "anything", ... )
);
print $lower_array_object["something"]; //prints "anything"

Class

class CaseInsensitiveArray implements ArrayAccess
{
    private $_container = array();

    public function __construct( Array $initial_array = array() ) {
        $this->_container = array_map( "strtolower", $initial_array );
    }

    public function offsetSet($offset, $value) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        return isset($this->_container[$offset]);
    }

    public function offsetUnset($offset) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        return isset($this->container[$offset])
            ? $this->container[$offset]
            : null;
    }
}

A simple, but maybe expensive way, is to make a copy, then use array_change_key_case($array_copy, CASE_LOWER), and after that access array_copy['somekeyname']


I know this is an older question but the most elegant way to handle this problem is to use:

array_change_key_case($myArray); //second parameter is CASE_LOWER by default

In your example:

$myArray = array ('SOmeKeyNAme' => 7);
$myArray = array_change_key_case($myArray);

Afterwards $myArray will contain all lowercase keys:

echo $myArray['somekeyname'] will contain 7

Alternatively you can use:

array_change_key_case($myArray, CASE_UPPER);

Documentation be seen here: http://us3.php.net/manual/en/function.array-change-key-case.php


Option 1 - change the way you create the array

You can't do this without either a linear search or altering the original array. The most efficient approach will be to use strtolower on keys when you insert AND when you lookup values.

 $myArray[strtolower('SOmeKeyNAme')]=7;

 if (isset($myArray[strtolower('SomekeyName')]))
 {

 }

If it's important to you to preserve the original case of the key, you could store it as a additional value for that key, e.g.

$myArray[strtolower('SOmeKeyNAme')]=array('SOmeKeyNAme', 7);

Option 2 - create a secondary mapping

As you updated the question to suggest this wouldn't be possible for you, how about you create an array providing a mapping between lowercased and case-sensitive versions?

$keys=array_keys($myArray);
$map=array();
foreach($keys as $key)
{
     $map[strtolower($key)]=$key;
}

Now you can use this to obtain the case-sensitive key from a lowercased one

$test='somekeyname';
if (isset($map[$test]))
{
     $value=$myArray[$map[$test]];
}

This avoids the need to create a full copy of the array with a lower-cased key, which is really the only other way to go about this.

Option 3 - Create a copy of the array

If making a full copy of the array isn't a concern, then you can use array_change_key_case to create a copy with lower cased keys.

$myCopy=array_change_key_case($myArray, CASE_LOWER);

Tags:

Php

Arrays