Luigi Cavalieri - Authoring Open Source Code

How to Rename the Keys of an Element of a Multidimensional Associative Array While Preserving Elements' Order

When you want to rename a key without causing the elements of a multidimensional associative array to shuffle, native PHP functions alone aren't enough. Creativity has to absolutely come into play.

How to Rename the Keys of an Element of a Multidimensional Associative Array While Preserving Elements' Order

Renaming a key of an associative array in PHP is not a matter of magic, usually we can do it by assigning the value associated to the old key, to a new key, and unsetting the old element. But things complicate slightly when we want to rename a key without causing the elements of the array to shuffle. In such a case, native PHP functions alone aren't enough. Creativity has to absolutely come into play.

The solution I want to share with you is a procedural function that by knowing the new keys, and the keys to rename, it uses recursion to traverse a given multidimensional associative array and return a brand new array having all the elements in their original positions and the target element featured by the new keys.

The function is the following:

1/**
2 * Renames one key, or a hierarchy of keys, 
3 * of an element of a multidimensional associative array.
4 *
5 * @param array $array
6 * @param array $old_keys Hierarchy of keys to rename.
7 * @param array $new_keys Hierarchy of replacement keys. 
8 *                        It must have the same 
9 *                        number of elements of $old_keys.
10 * @return array
11 */
12function &rename_array_keys( &$array, $old_keys, $new_keys ) {
13  $new_array = array();
14
15  // With each recursive call we extract one key 
16  // from each of the two arrays of keys.
17  $old_key = array_shift( $old_keys );
18  $new_key = array_shift( $new_keys );
19
20  foreach ( $array as $key => &$value ) {
21    // When this check succeeds it does mean that 
22    // we have found the key to rename.
23    if ( $key === $old_key ) {
24      if (
25        // When $old_keys and $new_keys still contain 
26        // elements it does mean that we are renaming 
27        // a hierarchy of keys, not just a single key.
28        $old_keys && $new_keys && 
29
30        // Ensures that the recursive call is triggered 
31        // only if $value is an array and actually 
32        // contains the next key to rename ( $old_keys[0] ).
33        isset( $value[$old_keys[0]] )
34      ) {
35        $new_array[$new_key] = rename_array_keys( $value, $old_keys, $new_keys ); 
36      }
37      else {
38        $new_array[$new_key] = $value;
39      }
40    }
41    else {
42      $new_array[$key] = $value;
43    }
44  }
45
46  return $new_array;
47}

In the event you rename the function when you include it into your code, don't forget to edit the recursive call!

Exemplification

Suppose you have the following multidimensional associative array...

1$dictionary = array(
2  'a' => 1,
3  'b' => array(
4    'x' => 22,
5    'y' => 23,
6    'z' => 24
7  ),
8  'c' => 3
9);

...and you want to rename the keys of the element $dictionary['b']['z']. The function should be called like this:

1$dictionary = rename_array_keys( $dictionary, array( 'b', 'z' ), array( 'green', 'blue' ) );

The resulting array will be this one:

1array(3) {
2  ["a"] => int(1)
3  ["green"] => array(3) {
4    ["x"]    => int(22)
5    ["y"]    => int(23)
6    ["blue"] => int(24)
7  }
8  ["c"] => int(3)
9}