You can change array key too easily but doing it without changing the order in PHP is quite tricky. Simply assigning the value to a new key and deleting old one doesn’t change the position of the new key at the place of old in the array.
So in this article, I have explained 3 ways to let you change array key while maintaining the key order and last one of them can be used with a multidimensional array as well. But before that, if you just need to rename a key without preserving the order, the two lines code does the job:
1 2 | $arr[$newkey] = $arr[$oldkey]; unset($arr[$oldkey]); |
1. Change Array Key using JSON encode/decode
1 2 3 4 | function json_change_key($arr, $oldkey, $newkey) { $json = str_replace('"'.$oldkey.'":', '"'.$newkey.'":', json_encode($arr)); return json_decode($json); } |
It’s short but be careful while using it. Use only to change key when you’re sure that your array doesn’t contain value exactly same as old key plus a colon. Otherwise, the value or object value will also get replaced.
2. Replace key & Maintain Order using Array Functions in PHP
1 2 3 4 5 6 7 8 | function replace_key($arr, $oldkey, $newkey) { if(array_key_exists( $oldkey, $arr)) { $keys = array_keys($arr); $keys[array_search($oldkey, $keys)] = $newkey; return array_combine($keys, $arr); } return $arr; } |
The functionreplace_key()
first checks if old key exists in the array? If yes then creates an Indexed Array of keys from source array and change old key with new using PHP array_search() function.
Finally, array_combine() function returns a new array with key changed, taking keys from the created indexed array and values from source array. The non-existence of old key just simply returns the array without any change.
3. Change Array Key without Changing the Order (Multidimensional Array Capable)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | //$arr => original array //$set => array containing old keys as keys and new keys as values function recursive_change_key($arr, $set) { if (is_array($arr) && is_array($set)) { $newArr = array(); foreach ($arr as $k => $v) { $key = array_key_exists( $k, $set) ? $set[$k] : $k; $newArr[$key] = is_array($v) ? recursive_change_key($v, $set) : $v; } return $newArr; } return $arr; } $ppl = array( 'jack' => array('address_2' => 'London', 'country' => 'UK'), 'jill' => array('address_2' => 'Washington', 'country' => 'US') ); $people = recursive_change_key($ppl, array('jill' => 'john', 'address_2' => 'city')); print_r($people); /* ==================================== Output: Array ( [jack] => Array ( [city] => London [country] => UK ) [john] => Array ( [city] => Washington [country] => US ) ) */ |
This solution is quite elegant and can work with multidimensional array too with help of classic PHP loop and recursive function call. Let’s see how are we doing this change.
Here we need to pass two arrays in the function call (Line #20). The first parameter is the array which needs to change keys and another is an array containing indexes as old keys and values as new keys. Upon execution, the function will change all the keys in the first array which are present in the second array too and their respective values will be new keys.
The recursive calling within function ensures changing keys up to the deepest branch of the array. The functionrecursive_change_key()
here is provided along with the example to understand better.
Don’t forget to read our extensive list of 38 PHP related tutorials yet.
So here you got 3 ways to change array key without changing the order of array in PHP. And the last one works with a multidimensional array as well. All you need is just to provide correct set of “old key, new key” pairs for changing purpose.
Just wanted to thank oyu. Method 2 workd fantastic for me
Method 2 will fail if you have mixed key with a 0 index, as array_search without the strict flag will match 0 to any non numerical stirng.
I added a check for a numerical string and cast it to int:
public function replace_key( array $array, $oldKey, $newKey ) : array
{
if ( ! array_key_exists( $oldKey, $array ) )
{
return $array;
}
$keys = array_keys( $array );
if ( is_string( $oldKey ) && is_numeric( $oldKey ) && strpos( $oldKey, ‘.’ ) === false )
{
$oldKey = (int) $oldKey;
}
$keys[ array_search( $oldKey, $keys, true ) ] = $newKey;
return array_combine( $keys, $array );
}
PHP Unit test ->
public function testRenameKeyPreservingOrder() : void
{
$array = [
‘a’ => ‘ay’,
0 => ‘zero’,
‘b’ => ‘be’,
‘1.1’ => ‘one point one’,
‘c’ => ‘ce’,
3 => ‘three’,
];
// Check nothing happens if the key isn’t present
$this->assertSame( $array, \TGHelpers_Array::renameKeyKeepingOrder( $array, ‘foo’, ‘bar’ ) );
// Check string keys
$this->assertSame(
[
‘a’ => ‘ay’,
0 => ‘zero’,
‘buh’ => ‘be’,
‘1.1’ => ‘one point one’,
‘c’ => ‘ce’,
3 => ‘three’,
],
\TGHelpers_Array::renameKeyKeepingOrder( $array, ‘b’, ‘buh’ )
);
// Check “float” (string) keys
$this->assertSame(
[
‘a’ => ‘ay’,
0 => ‘zero’,
‘b’ => ‘be’,
‘5’ => ‘one point one’,
‘c’ => ‘ce’,
3 => ‘three’,
],
\TGHelpers_Array::renameKeyKeepingOrder( $array, ‘1.1’, 5 )
);
// Check numerical
$this->assertSame(
[
‘a’ => ‘ay’,
0 => ‘zero’,
‘b’ => ‘be’,
‘1.1’ => ‘one point one’,
‘c’ => ‘ce’,
5 => ‘three’,
],
\TGHelpers_Array::renameKeyKeepingOrder( $array, 3, 5 )
);
// Check numerical as string
$this->assertSame(
[
‘a’ => ‘ay’,
0 => ‘zero’,
‘b’ => ‘be’,
‘1.1’ => ‘one point one’,
‘c’ => ‘ce’,
5 => ‘three’,
],
\TGHelpers_Array::renameKeyKeepingOrder( $array, ‘3’, 5 )
);
}
Edit: ( in the unit test \TGHelpers_Array::renameKeyKeepingOrder is where i put the function replace_key() )
It’s nice that you improved the function to consist of numeric/floating keys.
A little bit more complicated, but can do associative arrays with out having to create a new array: http://php.net/manual/en/function.array-walk.php#122991
@ellisgl:disqus
That’s good. Yet that piece of code requires more processing time as well as passing many parameters which isn’t less than memory occupied by the temporary array created here.
@ellisgl:disqus
That’s good. Yet that piece of code requires more processing time as well as passing many parameters which isn’t less than memory occupied by the temporary array created here.
I didn’t say it was a better way, just another way. =P
Haha lol. I admit you’re smarter than me.
I wouldn’t say I’m “smart”. Just more determine to do crazy things.
That’s nice habit until things don’t get complicated :-D. Have a good time ahead!
I put together some benchmarks: https://github.com/ellisgl/php-benchmarks/blob/master/results/RootLevelArrayKeyRename.md
Serialization, regular expression and JSON string always have performance issue. Rest all are around near except the benchArrayKeys.
I think there is a typo
Line 6 : it rather be
$newArr[$key] = is_array($v) ? recursive_change_key($v, $set) : $v;
because it’s recursive 😀