7

Is there a "better" way (built-in function, better algorithm) to normalize the case of all the keys in a PHP array? Looping though and creating a new array works

$new = array();
foreach( $old as $key=>$value) {
    $key = strToLower($key);
    if(!array_key_exists($key,$new) {
        $new[$key] = $value;
    } 
    else {
        throw new Exception('Duplicate Key Encountered');
    }

}

but it seems like these should be a way to do this "in place".

Update: It looks like there is a built in, the not deceptively named yet somehow missed by me array_change_key_case. I'd still be interesting in seeing algorithmic approaches that would let you better handle what happens when you hit "duplicate" keys.

2
  • For the algorithmic approach I'd go with with soulmerge's "pragmatic" version below. Commented Jul 23, 2009 at 14:10
  • This post explains what you need Commented Jul 10, 2014 at 21:06

5 Answers 5

13

I believe array_change_key_case does what you're looking for.

https://www.php.net/manual/en/function.array-change-key-case.php

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

Comments

4

I found that builtin functions are much faster than loops when processing large arrays. This might do what you want (untested code):

$lowerCaseKeys = array_map('strtolower', array_keys($array));
$duplicates = array_filter(array_count_values($lowerCaseKeys), create_function('$count', 'return $count > 1;'));
if (!empty($duplicates)) {
    throw new Exception('duplicate keys found: ' . implode(',', array_keys($duplicates)));
}
# Recreate the array with lower-case keys
$array = array_combine($lowerCaseKeys, array_values($array));

EDIT Or the pragmatic approach (should be much faster):

$lowerCaseKeyArray = array_change_key_case($array);
if (count($lowerCaseKeyArray) !== count($array)) {
    # You can extract the duplicate keys here as above, if you like
    throw new Exception('duplicate keys found!');
}

1 Comment

Yeah, builtins are almost always going to be faster. When it's Compiled C vs. PHP Opt-Code, guess who wins :)
3

You could use array_change_key_case(). This can cause array keys to be overwritten, so you would want to compare the array sizes using count() before and after you do the key case change. Because of the counts(), I'm not sure if this method would give you better performance or not, you'd have to benchmark it.

$new = array_change_key_case($old, CASE_LOWER);
if (count($new) < count($old)) {
    throw new Exception("Duplicate key encountered.");
}

Comments

0
foreach(array_keys($old) as $key) {
  $lower = strtolower($key);
  //if key is already lower case, do nothing
  if($key == $lower)
    continue;
  $value = $old[$key];
  unset($old[$key]);
  $old[$lower] = $value;
}

Comments

0

Support for multidimensional arrays, inspired from this PHP manual comment:

function array_change_key_case_recursive($input, $case = CASE_LOWER)
{
    if (!is_array($input))
    {
        trigger_error("Invalid input array '{$array}'", E_USER_NOTICE);
        return false;
    }

    if (!in_array($case, array(CASE_UPPER, CASE_LOWER)))
    {
        trigger_error("Case parameter '{$case}' is invalid.", E_USER_NOTICE);
        return false;
    }

    $input = array_change_key_case($input, $case);

    foreach($input as $key => $array)
        if(is_array($array))
            $input[$key] = array_change_key_case_recursive($array, $case);

    return $input;
}

For better performance, it uses the native array_change_key_case() PHP function.

Comments

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.