views:

606

answers:

4

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.

+1  A: 
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;
}
Frank Farmer
+9  A: 

I believe array_change_key_case does what you're looking for.

http://us3.php.net/manual/en/function.array-change-key-case.php

acrosman
+2  A: 

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.");
}
zombat
+3  A: 

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!');
}
soulmerge
Yeah, builtins are almost always going to be faster. When it's Compiled C vs. PHP Opt-Code, guess who wins :)
Alan Storm