在PHP中,如何更改数组元素的键?

时间:2008-10-27 17:09:49

标签: php arrays associative-array

我有一个key => value形式的关联数组,其中key是一个数值,但它不是一个连续的数值。密钥实际上是一个ID号,值是一个计数。对于大多数实例来说这很好,但是我想要一个函数来获取数组的人类可读名称并将其用于键,而不更改值。

我没有看到这样做的函数,但我假设我需要提供旧密钥和新密钥(我都有)并转换数组。有没有一种有效的方法呢?

23 个答案:

答案 0 :(得分:505)

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

答案 1 :(得分:81)

执行此操作并保留数组顺序的方法是将数组键放入单独的数组中,查找并替换该数组中的键,然后将其与值组合。

这是一个功能:

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

答案 2 :(得分:49)

如果您的array是根据数据库查询构建的,则可以直接从mysql语句更改密钥:

而不是

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

使用类似的东西:

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

答案 3 :(得分:18)

KernelM的答案很好,但是为了避免Greg在评论中提出的问题(冲突的密钥),使用新的数组会更安全

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

答案 4 :(得分:16)

您可以使用第二个关联数组,将人类可读的名称映射到ID。这也将提供多对一的关系。然后做这样的事情:

echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];

答案 5 :(得分:10)

如果您还希望新数组键的位置与旧数组键的位置相同,则可以执行此操作:

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

答案 6 :(得分:6)

$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
];
*/

答案 7 :(得分:6)

这是一个帮助函数来实现:

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

非常基于@KernelM answer

用法:

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

成功重命名后会返回 true ,否则 false

答案 8 :(得分:6)

如果你的数组是递归的,你可以使用这个函数: 测试这些数据:

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

这是功能:

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

答案 9 :(得分:6)

我喜欢KernelM的解决方案,但我需要能够处理潜在关键冲突的东西(新密钥可能与现有密钥匹配)。以下是我提出的建议:

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

然后你可以像这样循环一个数组:

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

答案 10 :(得分:4)

此代码将有助于将旧密钥更改为新密钥

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

显示如

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

答案 11 :(得分:4)

简单的事情:

此函数将接受目标$ hash,$ replacementments也是包含 newkey =&gt; oldkey association 的哈希。

此功能将保留原始订单,但对于性能&amp ;;非常大(如10k以上的记录)数组可能会出现问题。存储器

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

这个替代功能会做同样的事情,更好的性能&amp;内存使用,以丢失原始顺序为代价(由于它是哈希表,因此不应该是一个问题!)

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

答案 12 :(得分:1)

这适用于重命名第一个键:

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

然后,print_r($ a)呈现修复的有序数组:

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

这适用于重命名任意键:

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

广义函数:

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

    return array_flip($tmp_A);
}

答案 13 :(得分:1)

如果您想一次更换多个键(保留顺序):

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

用法:

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

答案 14 :(得分:1)

在使用完整数组时,有一种替代方法可以更改数组元素的键 - 而无需更改数组的顺序。 它只是将数组复制到一个新数组中。

例如,我正在使用包含索引和关联键的混合多维数组 - 我想用它们的值替换整数键,而不会破坏顺序。

我是通过切换所有数字数组条目的键/值来实现的 - 这里:['0'=&gt;'foo']。请注意,订单完好无损。

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

输出:

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

答案 15 :(得分:1)

两种解决方案的简单基准比较。

解决方案1复制并删除(订单丢失)https://stackoverflow.com/a/240676/1617857     

for ($i =0; $i < 100000000; $i++){
    $array = ['test' => 'value'];
    $array['test2'] = $array['test'];
    unset($array['test']);
}

解决方案2重命名密钥https://stackoverflow.com/a/21299719/1617857     

for ($i =0; $i < 100000000; $i++){
    $array = ['test' => 'value'];
    $keys = array_keys( $array );
    $keys[array_search('test', $keys, true)] = 'test2';
    array_combine( $keys, $array );
}

结果:

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

答案 16 :(得分:0)

嗯,我之前没有测试过,但我觉得这段代码正常工作

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

答案 17 :(得分:0)

一个易于理解的保存器排序:

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

答案 18 :(得分:0)

您可以基于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));

它给出:

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

答案 19 :(得分:0)

最好的方法是使用引用,而不是未设置(这将清除内存)

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

解决方案:

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

您有一个原始名称和一个带有新名称的引用。

或者如果您不想在一个值中包含两个名称,则可以制作另一个选项卡并在引用时使用foreach

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

在键上进行迭代比克隆所有数组更好,并且如果您有较长的数据(例如100行+++等),则清理旧数组更好。

答案 20 :(得分:0)

您可以编写简单的函数,将回调应用于给定数组的键。类似于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}}

这里是要点https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php

答案 21 :(得分:0)

此基本功能可处理交换数组键并保持数组原始顺序...

2.5000    0.4397 
7.5000    0.4397
12.5000   0.6678
17.5000   0.6678
22.5000   1.6938
27.5000   1.6938
32.5000   2.2801
37.5000   2.2801
42.5000   2.5081
47.5000   2.5081
52.5000   1.6042
57.5000   1.6042
62.5000   0.6759
67.5000   0.6759
72.5000   0.3827
77.5000   0.3827
82.5000   0.2850
87.5000   0.2850
92.5000   0.1873
97.5000   0.1873

然后您可以循环浏览并用'z'交换所有'a'键...

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

答案 22 :(得分:0)

此功能将结合索引搜索来重命名数组键,并保持其位置。

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

用法:

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