In PHP, how do you change the key of an array element?

PhpArraysAssociative Array

Php Problem Overview


I have an associative array in the form key => value where key is a numerical value, however it is not a sequential numerical value. The key is actually an ID number and the value is a count. This is fine for most instances, however I want a function that gets the human-readable name of the array and uses that for the key, without changing the value.

I didn't see a function that does this, but I'm assuming I need to provide the old key and new key (both of which I have) and transform the array. Is there an efficient way of doing this?

Php Solutions


Solution 1 - Php

$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);

Solution 2 - Php

The way you would do this and preserve the ordering of the array is by putting the array keys into a separate array, find and replace the key in that array and then combine it back with the values.

Here is a function that does just that:

function change_key( $array, $old_key, $new_key ) {

    if( ! array_key_exists( $old_key, $array ) )
        return $array;

    $keys = array_keys( $array );
    $keys[ array_search( $old_key, $keys ) ] = $new_key;

    return array_combine( $keys, $array );
}

Solution 3 - Php

if your array is built from a database query, you can change the key directly from the mysql statement:

instead of

"select ´id´ from ´tablename´..."

use something like:

"select ´id´ **as NEWNAME** from ´tablename´..."

Solution 4 - Php

The answer from KernelM is nice, but in order to avoid the issue raised by Greg in the comment (conflicting keys), using a new array would be safer

$newarr[$newkey] = $oldarr[$oldkey];
$oldarr=$newarr;
unset($newarr);

Solution 5 - Php

You could use a second associative array that maps human readable names to the id's. That would also provide a Many to 1 relationship. Then do something like this: > echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];

Solution 6 - Php

$array = [
    'old1' => 1
    'old2' => 2
];

$renameMap = [
    'old1' => 'new1',   
    'old2' => 'new2'
];

$array = array_combine(array_map(function($el) use ($renameMap) {
    return $renameMap[$el];
}, array_keys($array)), array_values($array));

/*
$array = [
    'new1' => 1
    'new2' => 2
];
*/

Solution 7 - Php

If you want also the position of the new array key to be the same as the old one you can do this:

function change_array_key( $array, $old_key, $new_key) {
	if(!is_array($array)){ print 'You must enter a array as a haystack!'; exit; }
	if(!array_key_exists($old_key, $array)){
		return $array;
	}
	
	$key_pos = array_search($old_key, array_keys($array));
	$arr_before = array_slice($array, 0, $key_pos);
	$arr_after = array_slice($array, $key_pos + 1);
	$arr_renamed = array($new_key => $array[$old_key]);
	
	return $arr_before + $arr_renamed + $arr_after;
}

Solution 8 - Php

Simple benchmark comparison of both solution.

Solution 1 Copy and remove (order lost, but way faster) https://stackoverflow.com/a/240676/1617857

<?php
$array = ['test' => 'value', ['etc...']];

$array['test2'] = $array['test'];
unset($array['test']);

Solution 2 Rename the key https://stackoverflow.com/a/21299719/1617857

<?php
$array = ['test' => 'value', ['etc...']];

$keys = array_keys( $array );
$keys[array_search('test', $keys, true)] = 'test2';
array_combine( $keys, $array );

Benchmark:

<?php
$array = ['test' => 'value', ['etc...']];


for ($i =0; $i < 100000000; $i++){
    // Solution 1
}


for ($i =0; $i < 100000000; $i++){
    // Solution 2
}

Results:

php solution1.php  6.33s  user 0.02s system 99% cpu 6.356  total
php solution1.php  6.37s  user 0.01s system 99% cpu 6.390  total
php solution2.php  12.14s user 0.01s system 99% cpu 12.164 total
php solution2.php  12.57s user 0.03s system 99% cpu 12.612 total

Solution 9 - Php

If your array is recursive you can use this function: test this data:

    $datos = array
    (
        '0' => array
            (
                'no' => 1,
                'id_maquina' => 1,
                'id_transaccion' => 1276316093,
                'ultimo_cambio' => 'asdfsaf',
                'fecha_ultimo_mantenimiento' => 1275804000,
                'mecanico_ultimo_mantenimiento' =>'asdfas',
                'fecha_ultima_reparacion' => 1275804000,
                'mecanico_ultima_reparacion' => 'sadfasf',
                'fecha_siguiente_mantenimiento' => 1275804000,
                'fecha_ultima_falla' => 0,
                'total_fallas' => 0,
            ),

        '1' => array
            (
                'no' => 2,
                'id_maquina' => 2,
                'id_transaccion' => 1276494575,
                'ultimo_cambio' => 'xx',
                'fecha_ultimo_mantenimiento' => 1275372000,
                'mecanico_ultimo_mantenimiento' => 'xx',
                'fecha_ultima_reparacion' => 1275458400,
                'mecanico_ultima_reparacion' => 'xx',
                'fecha_siguiente_mantenimiento' => 1275372000,
                'fecha_ultima_falla' => 0,
                'total_fallas' => 0,
            )
    );

here is the function:

function changekeyname($array, $newkey, $oldkey)
{
   foreach ($array as $key => $value) 
   {
      if (is_array($value))
         $array[$key] = changekeyname($value,$newkey,$oldkey);
      else
      	{
		     $array[$newkey] =  $array[$oldkey];   	
      	}

   }
   unset($array[$oldkey]);      	
   return $array;	
}

Solution 10 - Php

I like KernelM's solution, but I needed something that would handle potential key conflicts (where a new key may match an existing key). Here is what I came up with:

function swapKeys( &$arr, $origKey, $newKey, &$pendingKeys ) {
    if( !isset( $arr[$newKey] ) ) {
        $arr[$newKey] = $arr[$origKey];
        unset( $arr[$origKey] );
        if( isset( $pendingKeys[$origKey] ) ) {
            // recursion to handle conflicting keys with conflicting keys
            swapKeys( $arr, $pendingKeys[$origKey], $origKey, $pendingKeys );
            unset( $pendingKeys[$origKey] );
        }
    } elseif( $newKey != $origKey ) {
        $pendingKeys[$newKey] = $origKey;
    }
}

You can then cycle through an array like this:

$myArray = array( '1970-01-01 00:00:01', '1970-01-01 00:01:00' );
$pendingKeys = array();
foreach( $myArray as $key => $myArrayValue ) {
    // NOTE: strtotime( '1970-01-01 00:00:01' ) = 1 (a conflicting key)
    $timestamp = strtotime( $myArrayValue );
    swapKeys( $myArray, $key, $timestamp, $pendingKeys );
}
// RESULT: $myArray == array( 1=>'1970-01-01 00:00:01', 60=>'1970-01-01 00:01:00' )

Solution 11 - Php

Here is a helper function to achieve that:

/**
 * Helper function to rename array keys.
 */
function _rename_arr_key($oldkey, $newkey, array &$arr) {
    if (array_key_exists($oldkey, $arr)) {
        $arr[$newkey] = $arr[$oldkey];
        unset($arr[$oldkey]);
        return TRUE;
    } else {
        return FALSE;
    }
}

pretty based on [@KernelM answer][1].

Usage:

_rename_arr_key('oldkey', 'newkey', $my_array);

It will return true on successful rename, otherwise false. [1]: https://stackoverflow.com/a/240676/55075

Solution 12 - Php

this code will help to change the oldkey to new one

$i = 0;
$keys_array=array("0"=>"one","1"=>"two");

$keys = array_keys($keys_array);

for($i=0;$i<count($keys);$i++) {
    $keys_array[$keys_array[$i]]=$keys_array[$i];
    unset($keys_array[$i]);
}
print_r($keys_array);

display like

$keys_array=array("one"=>"one","two"=>"two");

Solution 13 - Php

Easy stuff:

this function will accept the target $hash and $replacements is also a hash containing newkey=>oldkey associations.

This function will preserve original order, but could be problematic for very large (like above 10k records) arrays regarding performance & memory.

function keyRename(array $hash, array $replacements) {
	$new=array();
	foreach($hash as $k=>$v)
	{
	    if($ok=array_search($k,$replacements))
	        $k=$ok;
	    $new[$k]=$v;
	}
	return $new;	
}

this alternative function would do the same, with far better performance & memory usage, at the cost of loosing original order (which should not be a problem since it is hashtable!)

function keyRename(array $hash, array $replacements) {

	foreach($hash as $k=>$v)
	    if($ok=array_search($k,$replacements))
	    {
	      $hash[$ok]=$v;
	      unset($hash[$k]);
	    }

	return $hash;		
}

Solution 14 - Php

If you want to replace several keys at once (preserving order):

/**
 * Rename keys of an array
 * @param array $array (asoc)
 * @param array $replacement_keys (indexed)
 * @return array
 */
function rename_keys($array, $replacement_keys)  {
      return array_combine($replacement_keys, array_values($array));
}

Usage:

$myarr = array("a" => 22, "b" => 144, "c" => 43);
$newkeys = array("x","y","z");
print_r(rename_keys($myarr, $newkeys));
//must return: array("x" => 22, "y" => 144, "z" => 43);

Solution 15 - Php

There is an alternative way to change the key of an array element when working with a full array - without changing the order of the array. It's simply to copy the array into a new array.

For instance, I was working with a mixed, multi-dimensional array that contained indexed and associative keys - and I wanted to replace the integer keys with their values, without breaking the order.

I did so by switching key/value for all numeric array entries - here: ['0'=>'foo']. Note that the order is intact.

<?php
$arr = [
	'foo',
	'bar'=>'alfa',
	'baz'=>['a'=>'hello', 'b'=>'world'],
];

foreach($arr as $k=>$v) {
	$kk = is_numeric($k) ? $v : $k;
	$vv = is_numeric($k) ? null : $v;
	$arr2[$kk] = $vv;
}

print_r($arr2);

Output:

Array (
    [foo] => 
    [bar] => alfa
    [baz] => Array (
            [a] => hello
            [b] => world
        )
)

Solution 16 - Php

You can use this function based on array_walk:

function mapToIDs($array, $id_field_name = 'id')
{
	$result = [];
	array_walk($array, 
		function(&$value, $key) use (&$result, $id_field_name)
		{
			$result[$value[$id_field_name]] = $value;
		}
	);
	return $result;
}

$arr = [0 => ['id' => 'one', 'fruit' => 'apple'], 1 => ['id' => 'two', 'fruit' => 'banana']];
print_r($arr);
print_r(mapToIDs($arr));

It gives:

Array(
    [0] => Array(
        [id] => one
        [fruit] => apple
    )
    [1] => Array(
        [id] => two
        [fruit] => banana
    )
)

Array(
    [one] => Array(
        [id] => one
        [fruit] => apple
    )
    [two] => Array(
        [id] => two
        [fruit] => banana
    )
)

Solution 17 - Php

This function will rename an array key, keeping its position, by combining with index searching.

function renameArrKey($arr, $oldKey, $newKey){
    if(!isset($arr[$oldKey])) return $arr; // Failsafe
    $keys = array_keys($arr);
    $keys[array_search($oldKey, $keys)] = $newKey;
    $newArr = array_combine($keys, $arr);
    return $newArr;
}

Usage:

$arr = renameArrKey($arr, 'old_key', 'new_key');

Solution 18 - Php

This page has been peppered with a wide interpretation of what is required because there is no minimal, verifiable example in the question body. Some answers are merely trying to solve the "title" without bothering to understand the question requirements.

> The key is actually an ID number and the value is a count. This is > fine for most instances, however I want a function that gets the > human-readable name of the array and uses that for the key, without > changing the value.

PHP keys cannot be changed but they can be replaced -- this is why so many answers are advising the use of array_search() (a relatively poor performer) and unset().

Ultimately, you want to create a new array with names as keys relating to the original count. This is most efficiently done via a lookup array because searching for keys will always outperform searching for values.

Code: (Demo)

$idCounts = [
    3 => 15,
    7 => 12,
    8 => 10,
    9 => 4
];

$idNames = [
    1 => 'Steve',
    2 => 'Georgia',
    3 => 'Elon',
    4 => 'Fiona',
    5 => 'Tim',
    6 => 'Petra',
    7 => 'Quentin',
    8 => 'Raymond',
    9 => 'Barb'
];

$result = [];
foreach ($idCounts as $id => $count) {
    if (isset($idNames[$id])) {
        $result[$idNames[$id]] = $count;
    }
}
var_export($result);

Output:

array (
  'Elon' => 15,
  'Quentin' => 12,
  'Raymond' => 10,
  'Barb' => 4,
)

This technique maintains the original array order (in case the sorting matters), doesn't do any unnecessary iterating, and will be very swift because of isset().

Solution 19 - Php

this works for renaming the first key:

$a = ['catine' => 'cat', 'canine'  => 'dog'];
$tmpa['feline'] = $a['catine'];
unset($a['catine']);
$a = $tmpa + $a;

then, print_r($a) renders a repaired in-order array:

Array
(
    [feline] => cat
    [canine] => dog
)

this works for renaming an arbitrary key:

$a = ['canine'  => 'dog', 'catine' => 'cat', 'porcine' => 'pig']
$af = array_flip($a)
$af['cat'] = 'feline';
$a = array_flip($af)

print_r($a)

Array
(
    [canine] => dog
    [feline] => cat
    [porcine] => pig
)

a generalized function:

function renameKey($oldkey, $newkey, $array) {
    $val = $array[$oldkey];
    $tmp_A = array_flip($array);
    $tmp_A[$val] = $newkey;

    return array_flip($tmp_A);
}

Solution 20 - Php

best way is using reference, and not using unset (which make another step to clean memory)

$tab = ['two' => [] ];

solution:

$tab['newname'] = & $tab['two'];

you have one original and one reference with new name.

or if you don't want have two names in one value is good make another tab and foreach on reference

foreach($tab as $key=> & $value) {
    if($key=='two') { 
        $newtab["newname"] = & $tab[$key];
     } else {
        $newtab[$key] = & $tab[$key];
     }
}

Iterration is better on keys than clone all array, and cleaning old array if you have long data like 100 rows +++ etc..

Solution 21 - Php

This basic function handles swapping array keys and keeping the array in the original order...

public function keySwap(array $resource, array $keys)
{
    $newResource = [];

    foreach($resource as $k => $r){
        if(array_key_exists($k,$keys)){
            $newResource[$keys[$k]] = $r;
        }else{
            $newResource[$k] = $r;
        }
    }

    return $newResource;
}

You could then loop through and swap all 'a' keys with 'z' for example...

$inputs = [
  0 => ['a'=>'1','b'=>'2'],
  1 => ['a'=>'3','b'=>'4']
]

$keySwap = ['a'=>'z'];

foreach($inputs as $k=>$i){
    $inputs[$k] = $this->keySwap($i,$keySwap);
}

Solution 22 - Php

One which preservers ordering that's simple to understand:

function rename_array_key(array $array, $old_key, $new_key) {
  if (!array_key_exists($old_key, $array)) {
      return $array;
  }
  $new_array = [];
  foreach ($array as $key => $value) {
    $new_key = $old_key === $key
      ? $new_key
      : $key;
    $new_array[$new_key] = $value;
  }
  return $new_array;
}

Solution 23 - Php

You can write simple function that applies the callback to the keys of the given array. Similar to array_map

<?php
function array_map_keys(callable $callback, array $array) {
    return array_merge([], ...array_map(
        function ($key, $value) use ($callback) { return [$callback($key) => $value]; },
        array_keys($array),
        $array
    ));
}

$array = ['a' => 1, 'b' => 'test', 'c' => ['x' => 1, 'y' => 2]];
$newArray = array_map_keys(function($key) { return 'new' . ucfirst($key); }, $array);

echo json_encode($array); // {"a":1,"b":"test","c":{"x":1,"y":2}}
echo json_encode($newArray); // {"newA":1,"newB":"test","newC":{"x":1,"y":2}}

Here is a gist https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php.

Solution 24 - Php

Hmm, I'm not test before, but I think this code working

function replace_array_key($data) {
    $mapping = [
        'old_key_1' => 'new_key_1',
        'old_key_2' => 'new_key_2',
    ];

    $data = json_encode($data);
    foreach ($mapping as $needed => $replace) {
        $data = str_replace('"'.$needed.'":', '"'.$replace.'":', $data);
    }

    return json_decode($data, true);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThomas OwensView Question on Stackoverflow
Solution 1 - PhpKernelMView Answer on Stackoverflow
Solution 2 - PhpDiverseAndRemote.comView Answer on Stackoverflow
Solution 3 - PhpSimon FrancoView Answer on Stackoverflow
Solution 4 - PhpkjgView Answer on Stackoverflow
Solution 5 - PhpTom RitterView Answer on Stackoverflow
Solution 6 - PhptemuriView Answer on Stackoverflow
Solution 7 - PhpspreadzzView Answer on Stackoverflow
Solution 8 - PhpLéo BenoistView Answer on Stackoverflow
Solution 9 - PhppajafumoView Answer on Stackoverflow
Solution 10 - PhpkingjeffreyView Answer on Stackoverflow
Solution 11 - PhpkenorbView Answer on Stackoverflow
Solution 12 - PhpKarthikeyan GanesanView Answer on Stackoverflow
Solution 13 - PhpNadirView Answer on Stackoverflow
Solution 14 - PhplepeView Answer on Stackoverflow
Solution 15 - PhpKristoffer BohmannView Answer on Stackoverflow
Solution 16 - PhpAlekzanderView Answer on Stackoverflow
Solution 17 - PhpGrantView Answer on Stackoverflow
Solution 18 - PhpmickmackusaView Answer on Stackoverflow
Solution 19 - PhpwmmsoView Answer on Stackoverflow
Solution 20 - PhpKamil DąbrowskiView Answer on Stackoverflow
Solution 21 - PhpMikeyJView Answer on Stackoverflow
Solution 22 - PhpAndrewView Answer on Stackoverflow
Solution 23 - PhpvardiusView Answer on Stackoverflow
Solution 24 - PhpFrank VuView Answer on Stackoverflow