79

When I var_dump on a variable called $tags (a multidimensional array) I get this:

Array
(
    [0] => Array
        (
            [name] => tabbing
            [url] => tabbing
        )

    [1] => Array
        (
            [name] => tabby ridiman
            [url] => tabby-ridiman
        )

    [2] => Array
        (
            [name] => tables
            [url] => tables
        )

    [3] => Array
        (
            [name] => tabloids
            [url] => tabloids
        )

    [4] => Array
        (
            [name] => taco bell
            [url] => taco-bell
        )

    [5] => Array
        (
            [name] => tacos
            [url] => tacos
        )
)

I would like to rename all array keys called "url" to be called "value". What would be a good way to do this?

2

14 Answers 14

170

You could use array_map() to do it.

$tags = array_map(function($tag) {
    return array(
        'name' => $tag['name'],
        'value' => $tag['url']
    );
}, $tags);
Sign up to request clarification or add additional context in comments.

4 Comments

nice! quick note: closures (anonymous functions) are only available in php 5.3.0+
quick note: You need to be using PHP 5.6 or greater, otherwise you're running an unsupported version of php and can possibly expect security issues.
Hello, I have a case with several columns, is there a way to use similar function that does not overwrite each item, but just alter? So much coding else...
Warning: this will erase all keys that you did not rename.
42

Loop through, set new key, unset old key.

foreach($tags as &$val){
    $val['value'] = $val['url'];
    unset($val['url']);
}

Comments

8

Recursive php rename keys function:

function replaceKeys($oldKey, $newKey, array $input){
    $return = array(); 
    foreach ($input as $key => $value) {
        if ($key===$oldKey)
            $key = $newKey;

        if (is_array($value))
            $value = replaceKeys( $oldKey, $newKey, $value);

        $return[$key] = $value;
    }
    return $return; 
}

1 Comment

This is a brilliant solution! it renames the key wherever it is in the multi-dimensional array. Thank you this saved me hours of work.
8

Talking about functional PHP, I have this more generic answer:

    array_map(function($arr){
        $ret = $arr;
        $ret['value'] = $ret['url'];
        unset($ret['url']);
        return $ret;
    }, $tag);
}

Comments

6
foreach ($basearr as &$row)
{
    $row['value'] = $row['url'];
    unset( $row['url'] );
}

unset($row);

2 Comments

Warning: Reference of $row and the last array element remain even after the foreach loop. It is recommended to destroy it by unset(). Otherwise you may experience unexpected behavior. See secure.php.net/manual/en/control-structures.foreach.php, stackoverflow.com/q/3307409, stackoverflow.com/q/4969243
At least you don't use $row after the iteration and foreach is executed inside a function, it will automatically destroyed after the end of function. Sometime $row can be useful if you have break the iteration and want to use the last iterated element outside foreach.
3

This should work in most versions of PHP 4+. Array map using anonymous functions is not supported below 5.3.

Also the foreach examples will throw a warning when using strict PHP error handling.

Here is a small multi-dimensional key renaming function. It can also be used to process arrays to have the correct keys for integrity throughout your app. It will not throw any errors when a key does not exist.

function multi_rename_key(&$array, $old_keys, $new_keys)
{
    if(!is_array($array)){
        ($array=="") ? $array=array() : false;
        return $array;
    }
    foreach($array as &$arr){
        if (is_array($old_keys))
        {
            foreach($new_keys as $k => $new_key)
            {
                (isset($old_keys[$k])) ? true : $old_keys[$k]=NULL;
                $arr[$new_key] = (isset($arr[$old_keys[$k]]) ? $arr[$old_keys[$k]] : null);
                unset($arr[$old_keys[$k]]);
            }
        }else{
            $arr[$new_keys] = (isset($arr[$old_keys]) ? $arr[$old_keys] : null);
            unset($arr[$old_keys]);
        }
    }
    return $array;
}

Usage is simple. You can either change a single key like in your example:

multi_rename_key($tags, "url", "value");

or a more complex multikey

multi_rename_key($tags, array("url","name"), array("value","title"));

It uses similar syntax as preg_replace() where the amount of $old_keys and $new_keys should be the same. However when they are not a blank key is added. This means you can use it to add a sort if schema to your array.

Use this all the time, hope it helps!

3 Comments

Or you can just use array_map($tags,create_function('$tag','return array( "name" => $tag["name"], "value" => $tag["url"]'));
That does get messy when you are renaming systematically. Also create_function uses eval, which is obviously to be avoided if possible.
why so unnecessarily complicated?
1

Very simple approach to replace keys in a multidimensional array, and maybe even a bit dangerous, but should work fine if you have some kind of control over the source array:

$array = [ 'oldkey' => [ 'oldkey' => 'wow'] ];
$new_array = json_decode(str_replace('"oldkey":', '"newkey":', json_encode($array)));
print_r($new_array); // [ 'newkey' => [ 'newkey' => 'wow'] ]

2 Comments

can it work if I want to replace all the keys in this array to "q"? {"q0":"String1","q1":"string2","q2":"string3"} I need to have it like this: {"q":"String1","q":"string2","q":"string3"} it is the requirement for the multiline translation in google translation api v2... could it be possible?
no, That's impossible. Elements in a PHP array cannot have the same key at the same level. Also, the resulting string would not be a valid JSON string. (Because JSON also doesn't allow duplicate keys)
1

This doesn't have to be difficult in the least. You can simply assign the arrays around regardless of how deep they are in a multi-dimensional array:

$array['key_new'] = $array['key_old'];
unset($array['key_old']);

1 Comment

Must be $array['key_new'] = $array['key_old'];, of course. And it's a duplicate of this answer.
0
class DataHelper{

    private static function __renameArrayKeysRecursive($map = [], &$array = [], $level = 0, &$storage = []) {
        foreach ($map as $old => $new) {
            $old = preg_replace('/([\.]{1}+)$/', '', trim($old));
            if ($new) {
                if (!is_array($new)) {
                    $array[$new] = $array[$old];
                    $storage[$level][$old] = $new;
                    unset($array[$old]);
                } else {
                    if (isset($array[$old])) {
                        static::__renameArrayKeysRecursive($new, $array[$old], $level + 1, $storage);
                    } else if (isset($array[$storage[$level][$old]])) {
                        static::__renameArrayKeysRecursive($new, $array[$storage[$level][$old]], $level + 1, $storage);
                    }
                }
            }
        }
    }

    /**
     * Renames array keys. (add "." at the end of key in mapping array if you want rename multidimentional array key).
     * @param type $map
     * @param type $array
    */
    public static function renameArrayKeys($map = [], &$array = [])
    {
        $storage = [];
        static::__renameArrayKeysRecursive($map, $array, 0, $storage);
        unset($storage);
    }
}

Use:

DataHelper::renameArrayKeys([
    'a' => 'b',
    'abc.' => [
       'abcd' => 'dcba'
    ]
], $yourArray);

Comments

0

It is from duplicated question

$json = '[   
{"product_id":"63","product_batch":"BAtch1","product_quantity":"50","product_price":"200","discount":"0","net_price":"20000"},    
{"product_id":"67","product_batch":"Batch2","product_quantity":"50","product_price":"200","discount":"0","net_price":"20000"}
]';

$array = json_decode($json, true);

$out = array_map(function ($product) {
  return array_merge([
    'price'    => $product['product_price'],
    'quantity' => $product['product_quantity'],
  ], array_flip(array_filter(array_flip($product), function ($value) {
    return $value != 'product_price' && $value != 'product_quantity';
  })));
}, $array);

var_dump($out);

https://repl.it/@Piterden/Replace-keys-in-array

Comments

0

This is how I rename keys, especially with data that has been uploaded in a spreadsheet:

function changeKeys($array, $new_keys) {
    $newArray = [];

    foreach($array as $row) {
        $oldKeys = array_keys($row);
        $indexedRow = [];

        foreach($new_keys as $index => $newKey)
            $indexedRow[$newKey] = isset($oldKeys[$index]) ? $row[$oldKeys[$index]] : '';

        $newArray[] = $indexedRow;
    }

    return $newArray;
}

Comments

0

Based on the great solution provided by Alex, I created a little more flexible solution based on a scenario I was dealing with. So now you can use the same function for multiple arrays with different numbers of nested key pairs, you just need to pass in an array of key names to use as replacements.

$data_arr = [
  0 => ['46894', 'SS'],
  1 => ['46855', 'AZ'],
];

function renameKeys(&$data_arr, $columnNames) {
  // change key names to be easier to work with.
  $data_arr = array_map(function($tag) use( $columnNames) {
    $tempArray = [];
    $foreachindex = 0;
    foreach ($tag as $key => $item) {
      $tempArray[$columnNames[$foreachindex]] = $item;
      $foreachindex++;
    }
    return $tempArray;
  }, $data_arr);

}

renameKeys($data_arr, ["STRATEGY_ID","DATA_SOURCE"]);

Comments

0

this work perfectly for me

 $some_options = array();;
if( !empty( $some_options ) ) {
   foreach( $some_options as $theme_options_key => $theme_options_value ) {
      if (strpos( $theme_options_key,'abc') !== false) { //first we check if the value contain 
         $theme_options_new_key = str_replace( 'abc', 'xyz', $theme_options_key ); //if yes, we simply replace
         unset( $some_options[$theme_options_key] );
         $some_options[$theme_options_new_key] = $theme_options_value;
      }
   }
}
return  $some_options;

Comments

0

You can do it without any loop

Like below

$tags = str_replace("url", "value", json_encode($tags));  
$tags = json_decode($tags, true);
                    

2 Comments

Bad practice. This will also change the array values if they have string "url" in them.
Yes, I know it, in that type of case don't use this solution.