如何在维护订单的同时更改数组中的键?

时间:2012-04-16 22:36:38

标签: php arrays

我如何做到这一点:

$array = array('a' => 1, 'd' => 2, 'c' => 3); //associative array

// rename $array['d'] as $array['b']
$array = replace_key_function($array, 'd', 'b');

var_export($array); // array('a' => 1, 'b' => 2, 'c' => 3); same order!

我没有看到这样做的功能。 有办法做到这一点吗?

5 个答案:

答案 0 :(得分:27)

http://ideone.com/nCZnY

$array = array('a' => 1, 'd' => 2, 'c' => 3); //associative array

// rename $array['d'] as $array['b']
$array = replace_key_function($array, 'd', 'b');

var_export($array); // array('a' => 1, 'b' => 2, 'c' => 3); same order!

function replace_key_function($array, $key1, $key2)
{
    $keys = array_keys($array);
    $index = array_search($key1, $keys);

    if ($index !== false) {
        $keys[$index] = $key2;
        $array = array_combine($keys, $array);
    }

    return $array;
}

答案 1 :(得分:4)

接受答案的逻辑存在缺陷。

如果您有这样的数组:

[
    'k1'=>'k1',
    'k2'=>'k2',
    'k3',
    'k4'=>'k4'
]

并替换' k4'用'东西'你会得到这样的输出:

[
    'k1'=>'k1',
    'k2'=>'k2',
    'something' => 'k3',
    'k4'=>'k4'
]

以下是解决问题的快速解决方法:

function replace_key_function($array, $key1, $key2)
{
    $keys = array_keys($array);
    //$index = array_search($key1, $keys);        
    $index = false;
    $i = 0;
    foreach($array as $k => $v){
        if($key1 === $k){
            $index = $i;
            break;
        }
        $i++;
    }

    if ($index !== false) {
        $keys[$index] = $key2;
        $array = array_combine($keys, $array);
    }

    return $array;
}

修改:2014年12月3日 如果将array_search的第三个参数(strict)设置为true,则接受的答案会起作用。

答案 2 :(得分:3)

您可以始终使用json_encode()拼合而不是使用循环,执行字符串替换,然后json_decode()返回数组:

function replaceKey($array, $old, $new)
{  
    //flatten the array into a JSON string
    $str = json_encode($array);

    // do a simple string replace.
    // variables are wrapped in quotes to ensure only exact match replacements
    // colon after the closing quote will ensure only keys are targeted 
    $str = str_replace('"'.$old.'":','"'.$new.'":',$str);

    // restore JSON string to array
    return json_decode($str, TRUE);       
}

现在这不会检查与预先存在的密钥的冲突(很容易添加字符串比较检查),并且它可能不是大规模数组中单个替换的最佳解决方案..但是有关扁平化的好处数组到一个替换字符串是因为它有效地使替换递归,因为任何深度的匹配都在一次传递中被替换:

$arr = array(
    array(
         'name'     => 'Steve'
        ,'city'     => 'Los Angeles'
        ,'state'    => 'CA'
        ,'country'  => 'USA'
        ,'mother'   => array(
             'name'     => 'Jessica'
            ,'city'     => 'San Diego'
            ,'state'    => 'CA'
            ,'country'  => 'USA'
        )
    )
    ,array(
         'name'     => 'Sara'
        ,'city'     => 'Seattle'
        ,'state'    => 'WA'
        ,'country'  => 'USA'
        ,'father'   =>  array(
             'name'     => 'Eric'
            ,'city'     => 'Atlanta'
            ,'state'    => 'GA'
            ,'country'  => 'USA'
            ,'mother'   => array(
                 'name'     => 'Sharon'
                ,'city'     => 'Portland'
                ,'state'    => 'OR'
                ,'country'  => 'USA'
            )
        )
    )
);
$replaced = replaceKey($arr,'city','town');
print_r($replaced);

输出

Array
(
    [0] => Array
        (
            [name] => Steve
            [town] => Los Angeles
            [state] => CA
            [country] => USA
            [mother] => Array
                (
                    [name] => Jessica
                    [town] => San Diego
                    [state] => CA
                    [country] => USA
                )
        )

    [1] => Array
        (
            [name] => Sara
            [town] => Seattle
            [state] => WA
            [country] => USA
            [father] => Array
                (
                    [name] => Eric
                    [town] => Atlanta
                    [state] => GA
                    [country] => USA
                    [mother] => Array
                        (
                            [name] => Sharon
                            [town] => Portland
                            [state] => OR
                            [country] => USA
                        )
                )
        )
)

答案 3 :(得分:2)

使用array_walk的PHP 5.3+的通用且简单的解决方案:

$array = array('a' => 1, 'd' => 2, 'c' => 3); //associative array

$array = replace_keys($array, array('d' => 'b'));
var_export($array); // array('a' => 1, 'b' => 2, 'c' => 3); same order!

function replace_keys(array $source, array $keyMapping) {
    $target = array();
    array_walk($source,
               function ($v, $k, $keyMapping) use (&$target) {
                    $mappedKey = isset($keyMapping[$k]) ? $keyMapping[$k] : $k;
                    $target[$mappedKey] = $v;
               },
               $keyMapping);
    return $target;
}

答案 4 :(得分:1)

已经公布了一个很好的答案,但这是我的两个便士:

$array = array('a'=>1, 'd'=>2, 'c'=>3);
// rename 'd' to 'b'
foreach($array as $k=>$v){
    if($k == 'd') { $k='b'; }
        $newarray[$k] = $v;
}
$array = $newarray;

对mike-purcell的回应对我上面的例子来说这是一个更容易接受的方法吗?

changeKey($array, 'd', 'b');

function changeKey($array, $oldKey, $newKey)
{
    foreach($array as $k=>$v){
        if($k == $oldKey) { $k = $newKey; }
        $returnArray[$k] = $v;
    }
    return $returnArray;
}

我一直在寻求提高:)