21

I have an array like below

$old = array(
       'a' => 'blah',
       'b' => 'key',
       'c' => 'amazing',
       'd' => array(
                0 => 'want to replace',
                1 => 'yes I want to'
              )
       );

I have another array having keys to replace with key information.

$keyReplaceInfoz = array('a' => 'newA', 'b' => 'newB', 'c' => 'newC', 'd' => 'newD');

I need to replace all keys of array $old with respective values in array $keyReplaceInfo.

Output should be like this

$old = array(
       'newA' => 'blah',
       'newB' => 'key',
       'newC' => 'amazing',
       'newD' => array(
                0 => 'want to replace',
                1 => 'yes I want to'
              )
       );

I had to do it manually as below. I am expecting better option. can anyone suggest better way to accomplish this?

$new = array();
foreach ($old as $key => $value)
{
     $new[$keyReplaceInfoz[$key]] = $value;
}

I know this can be more simpler.

nickb
  • 59,313
  • 13
  • 108
  • 143
Maulik Vora
  • 2,544
  • 5
  • 28
  • 48

11 Answers11

30
array_combine(array_merge($old, $keyReplaceInfoz), $old)

I think this looks easier than what you posed.

Summoner
  • 1,397
  • 1
  • 9
  • 9
  • 4
    `array_combine` will only work if the keys and values are in the correct order, and there is a replacement for every key. (I looked at this as a solution myself). – Leigh Jul 30 '12 at 14:10
  • Actually the only problem with the above is that it won't work if there isn't a replacement for every key. Ordering is not an issue because of array_merge($old, $keyReplaceInfoz). – Summoner Jul 30 '12 at 14:17
  • There's a couple of problems, both related to the numer of elements. If the replacement array contains a key that is not in the old array, there will be a PHP warning (and nothing will be replaced). If the replacement array is missing a key from the old array, the key in the old array will be replaced with it's own _value_ – Leigh Jul 30 '12 at 14:22
  • You are right. The line makes certain assumptions about the structure of $keyReplaceInfoz, the questioner should specify whether all of the keys would be available or not. – Summoner Jul 30 '12 at 14:25
  • ahh sorry, I am reading these comments after these much years, thanks @Summoner for awesome help at that time, And yes for my question and case, I had new keys available for each and every pair of old keys. – Maulik Vora Mar 24 '18 at 09:25
  • Actually you just need ```array_combine($keyReplaceInfoz, $old)``` or you'll be creating a different size array – Bruno de Oliveira Jul 23 '20 at 15:17
6
array_combine(
    ['newKey1', 'newKey2', 'newKey3'],
    array_values(['oldKey1' => 1, 'oldKey2' => 2, 'oldKey3' => 3])
);

This should do the trick as long as you have the same number of values and the same order.

Magarusu
  • 982
  • 10
  • 14
3

IMO using array_combine, array_merge, even array_intersect_key is overkill. The original code is good enough, and very fast.

Bohan Yang
  • 91
  • 1
  • 5
2

Adapting @shawn-k solution, here is more cleaner code using array_walk, it will only replace desired keys, of course you can modify as per your convenience

array_walk($old, function($value,$key)use ($keyReplaceInfoz,&$old){
        $newkey = array_key_exists($key,$keyReplaceInfoz)?$keyReplaceInfoz[$key]:false;
        if($newkey!==false){$old[$newkey] = $value;unset($old[$key]);
        }
    });

    print_r($old);
girish2040
  • 91
  • 3
1

I just solved this same problem in my own application, but for my application $keyReplaceInfoz acts like the whitelist- if a key is not found, that whole element is removed from the resulting array, while the matching whitelisted keys get translated to the new values.

I suppose you could apply this same algorithm maybe with less total code by clever usage of array_map (http://php.net/manual/en/function.array-map.php), which perhaps another generous reader will do.

function filterOldToAllowedNew($key_to_test){       
    return isset($keyReplaceInfoz[$key_to_test])?$keyReplaceInfoz[$key_to_test]:false;
}   

$newArray = array();

foreach($old as $key => $value){
    $newkey = filterOldToAllowedNew($key);
    if($newkey){
       $newArray[$newkey] = $value;
    }
}

print_r($newArray);
Shawn K
  • 11
  • 4
1

This question is old but since it comes up first on Google I thought I'd add solution.

// Subject
$old = array('foo' => 1, 'baz' => 2, 'bar' => 3));

// Translations    
$tr  = array('foo'=>'FOO', 'bar'=>'BAR');

// Get result
$new = array_combine(preg_replace(array_map(function($s){return "/^$s$/";}, 
           array_keys($tr)),$tr, array_keys($old)), $old);

// Output
print_r($new);

Result:

    
    Array
    (
       [FOO] => 1
       [baz] => 2
       [BAR] => 3
    )
Mark Thomson
  • 739
  • 5
  • 12
0

This the solution i have implemented for the same subject:

/**
 * Replace keys of given array by values of $keys
 * $keys format is [$oldKey=>$newKey]
 *
 * With $filter==true, will remove elements with key not in $keys
 *
 * @param  array   $array
 * @param  array   $keys
 * @param  boolean $filter
 *
 * @return $array
 */
function array_replace_keys(array $array,array $keys,$filter=false)
{
    $newArray=[];
    foreach($array as $key=>$value)
    {
        if(isset($keys[$key]))
        {
            $newArray[$keys[$key]]=$value;
        }
        elseif(!$filter)
        {
            $newArray[$key]=$value;
        }
    }

    return $newArray;
}
Juan Antonio Tubío
  • 1,172
  • 14
  • 28
  • How is this different than the method shown in question itself? – Maulik Vora Jul 03 '17 at 07:02
  • Because this method don't need have one replacement key for every key in the source array. The method shown in the question will give one error if any key of source array don't exists on replacement keys array – Juan Antonio Tubío Jul 03 '17 at 12:26
  • You are right Juan, but I was sure that I will have all keys available for replacement. the question was to improve the method. your method still does the same looping! – Maulik Vora Jul 06 '17 at 11:04
0

This works irrespective of array order & array count. Output order & value will be based on replaceKey.

$replaceKey = array('a' => 'newA', 'b' => 'newB', 'c' => 'newC', 'd' => 'newD', 'e' => 'newE','f'=>'newF');

$array = array(
       'a' => 'blah',
       'd' => array(
                0 => 'want to replace',
                1 => 'yes I want to'
              ),
       'noKey'=>'RESIDUAL',
       'c' => 'amazing',
       'b' => 'key',
       );

$filterKey = array_intersect_key($replaceKey,$array);
$filterarray = array_intersect_key(array_merge($filterKey,$array),$filterKey);

$replaced = array_combine($filterKey,$filterarray);

//output
var_export($replaced);
//array ( 'newA' => 'blah', 'newB' => 'key', 'newC' => 'amazing', 'newD' => array ( 0 => 'want to replace', 1 => 'yes I want to' ) )
Muthu Kumar
  • 420
  • 5
  • 7
0

If you're looking for a recursive solution to use on a multidimensional array, have a look at the below method. It will replace all keys requested, and leave all other keys alone.

/**
 * Given an array and a set of `old => new` keys,
 * will recursively replace all array keys that
 * are old with their corresponding new value.
 *
 * @param mixed $array
 * @param array $old_to_new_keys
 *
 * @return array
 */
function array_replace_keys($array, array $old_to_new_keys)
{
    if(!is_array($array)){
        return $array;
    }

    $temp_array = [];
    $ak = array_keys($old_to_new_keys);
    $av = array_values($old_to_new_keys);

    foreach($array as $key => $value){
        if(array_search($key, $ak, true) !== false){
            $key = $av[array_search($key, $ak)];
        }

        if(is_array($value)){
            $value = array_replace_keys($value, $old_to_new_keys);
        }

        $temp_array[$key] = $value;
    }

    return $temp_array;
}

Using OP's example array:

$old = array(
       'a' => 'blah',
       'b' => 'key',
       'c' => 'amazing',
       'd' => array(
                0 => 'want to replace',
                1 => 'yes I want to'
              )
       );
$replace = ["a" => "AA", 1 => 11];

var_export(array_replace_keys($old, $replace));

Gives the following output:

array (
  'AA' => 'blah',
  'b' => 'key',
  'c' => 'amazing',
  'd' => 
  array (
    0 => 'want to replace',
    11 => 'yes I want to',
  ),
)

DEMO

Inspired by the following snippet.

dearsina
  • 4,774
  • 2
  • 28
  • 34
0

This uses @Summoner's example but keeps @Leigh's hint in mind:

$start = microtime();
$array = [ "a" => 1, "b" => 2, "c" => 3 ];

function array_replace_key($array, $oldKey, $newKey) {
    $keys = array_keys($array);
    $idx = array_search($oldKey, $keys);
    array_splice($keys, $idx, 1, $newKey);
    return array_combine($keys, array_values($array));
}

print_r(array_replace_key($array, "b", "z"));
shaedrich
  • 5,457
  • 3
  • 26
  • 42
-1
    <?php
$new = array(); 

foreach ($old as $key => $value)
{
     $new[$keyReplaceInfoz][$key] = $value;

}
?>
chenio
  • 592
  • 3
  • 11
  • 27
  • This does not produce the output array the OP is asking for. Please check your code before posting. – Leigh Jul 30 '12 at 14:12