用给定的各自键替换数组键

21
我有一个如下的数组。
$old = array(
       'a' => 'blah',
       'b' => 'key',
       'c' => 'amazing',
       'd' => array(
                0 => 'want to replace',
                1 => 'yes I want to'
              )
       );

我有另一个数组,其中包含要替换为键信息的键。

$keyReplaceInfoz = array('a' => 'newA', 'b' => 'newB', 'c' => 'newC', 'd' => 'newD');
我需要用数组$keyReplaceInfo中相应的值替换数组$old中的所有键。

输出应该像这样:

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

我不得不手动完成以下操作,但我希望有更好的选项。 有人能建议更好的方法吗?

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

我知道这可以更简单。

11个回答

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

我认为这比你提出的问题更容易。


4
只有在键和值的顺序正确并且每个键都有对应的值时,array_combine 函数才能正常工作(我自己也尝试过这种解决方案)。 - Leigh
实际上,以上唯一的问题是,如果没有每个键的替换,它将无法工作。由于array_merge($old, $keyReplaceInfoz),排序不是问题。 - Summoner
有几个问题,都与元素数量有关。如果替换数组包含一个旧数组中没有的键,则会出现PHP警告(并且不会被替换)。如果替换数组缺少旧数组中的键,则旧数组中的键将被替换为它自己的_value_。 - Leigh
你是对的。这行代码对$keyReplaceInfoz的结构做出了一些假设,提问者应该明确指定是否所有的键都可用。 - Summoner
啊,抱歉,这么多年后我才看到这些评论,感谢@Summoner在那个时候提供的帮助。对于我的问题和情况,是针对每一对旧密钥都有新密钥可用。 - Maulik Vora
实际上,你只需要使用array_combine($keyReplaceInfoz, $old),否则你将会创建一个不同大小的数组。 - Bruno de Oliveira

6
array_combine(
    ['newKey1', 'newKey2', 'newKey3'],
    array_values(['oldKey1' => 1, 'oldKey2' => 2, 'oldKey3' => 3])
);

只要您具有相同数量和相同顺序的值,这应该可以解决问题。

array_values()不重要,因为array_combine()会忽略它的两个参数的键。 - undefined

3

使用array_combine、array_merge甚至array_intersect_key都有些过头了。 原始代码足够好,而且速度非常快。


2

借鉴@shawn-k的解决方案,这里使用array_walk编写更简洁的代码,它将仅替换所需的键名,当然您可以根据自己的需要进行修改。

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);

1
这个问题很旧,但因为它在谷歌上排名第一,所以我想添加解决方案。
// 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);

结果:

    数组
    (
        [FOO] => 1
        [baz] => 2
        [BAR] => 3
    )

这个答案缺少教育性的解释。 - mickmackusa

1
我刚在自己的应用程序中解决了同样的问题,但对于我的应用程序,$keyReplaceInfoz 就像白名单-如果找不到一个键,则整个元素将从结果数组中删除,而匹配的白名单键会被翻译成新值。
我想你可以通过巧妙地使用 array_map(http://php.net/manual/en/function.array-map.php)应用相同的算法,也许另一个慷慨的读者会这样做。
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);

0

这是我为同一主题实施的解决方案:

/**
 * 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;
}

这与问题本身中展示的方法有何不同? - Maulik Vora
因为这种方法不需要为源数组中的每个键都有一个替换键。如果源数组的任何键不存在于替换键数组中,问题中显示的方法将会出现一个错误。 - Juan Antonio Tubío
你是对的Juan,但我确信我将拥有所有可用于替换的键。问题在于改进方法。你的方法仍然执行相同的循环! - Maulik Vora

0
如果您正在寻找适用于多维数组的递归解决方案,请查看下面的方法。它将替换所有请求的键,并保留所有其他键不变。
/**
 * 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;
}

使用 OP 的示例数组:

$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));

输出以下内容:

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

演示

受到以下代码片段的启发。


0

这个使用了@Summoner例子,但是记住了@Leigh提示

$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"));

0

无论数组的顺序和数量如何,这都适用。输出的顺序和值将基于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' ) )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接