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

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


当前回答

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

其他回答

如果你的数组是从数据库查询中构建的,你可以直接从mysql语句中更改键:

而不是

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

可以使用以下语句:

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

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

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

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

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

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

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

解决方案2密钥重命名为“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 );

基准:

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


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


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

结果:

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

做到这一点并保持数组顺序的方法是将数组键放入一个单独的数组中,找到并替换该数组中的键,然后将其与值组合起来。

这里有一个函数就是这样做的:

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

本页对所要求的内容进行了广泛的解释,因为问题主体中没有最小的、可验证的示例。有些答案只是试图解决“标题”,而不费心去理解问题的要求。

键实际上是一个ID号,值是一个计数。这是 大多数情况下都没问题,但是我想要一个函数 人类可读的数组名称,并使用该名称作为键,无需 更改值。

PHP键不能被更改,但可以被替换——这就是为什么这么多答案建议使用array_search()(一个相对较差的性能)和unset()。

最终,您希望创建一个新数组,其名称作为与原始计数相关的键。这是通过查找数组最有效地完成的,因为搜索键总是比搜索值更好。

代码:(演示)

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

输出:

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

这种技术保持原始的数组顺序(以防排序问题),不做任何不必要的迭代,而且由于isset()的存在,速度非常快。