Trong PHP, làm thế nào để bạn thay đổi khóa của một phần tử mảng?


348

Tôi có một mảng kết hợp ở dạng key => valuekhóa trong đó khóa là một giá trị số, tuy nhiên nó không phải là giá trị số liên tiếp. Khóa thực sự là một số ID và giá trị là một số đếm. Điều này tốt cho hầu hết các trường hợp, tuy nhiên tôi muốn một hàm lấy tên con người có thể đọc được của mảng và sử dụng nó cho khóa, mà không thay đổi giá trị.

Tôi đã không thấy một chức năng thực hiện điều này, nhưng tôi cho rằng tôi cần cung cấp khóa cũ và khóa mới (cả hai đều có) và chuyển đổi mảng. Có một cách hiệu quả để làm điều này?


Câu trả lời:


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

5
Chỉ cần cẩn thận rằng 1) Không có hai khóa nào có cùng phiên bản có thể đọc được bằng con người 2) Không có phiên bản nào có thể đọc được bằng con người
Greg

81
Ngoài ra, điều này có lẽ sẽ thay đổi thứ tự của mảng, mà bạn có thể cần phải cẩn thận. Ngay cả các mảng kết hợp trong PHP cũng được sắp xếp và đôi khi thứ tự đó được tận dụng.
Robin Winslow

7
Vâng, điểm tuyệt vời Robin. Có cách nào để giữ trật tự như vậy? Hay bạn cần tạo một mảng mới để đạt được điều đó?
Simon East

40
Câu hỏi thưởng: Làm thế nào để thay đổi ID, nhưng duy trì thứ tự mảng?
Petr Peller

17
nếu giá trị khóa không thay đổi, bạn sẽ xóa một phần tử mảng. Bạn có thể muốn kiểm tra nó.
Peeech

97

Cách bạn sẽ làm điều này và duy trì thứ tự của mảng là bằng cách đặt các khóa mảng thành một mảng riêng, tìm và thay thế khóa trong mảng đó và sau đó kết hợp lại với các giá trị.

Đây là một chức năng thực hiện điều đó:

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
Cảm ơn điều này thực sự hữu ích vì tôi cần phải giữ trật tự của mảng. Tôi đã thử câu trả lời được chấp nhận trước khi tôi tìm thấy trang này.
gillytech

3
Có nhiều thích giữ trật tự của mảng, trông gọn gàng hơn.
Phil Cook

2
Phải giữ trật tự quan trọng, tốt, làm việc như một cơ duyên!
Học viên

Lưu ý nếu bạn muốn biểu diễn hoặc bảo quản đơn hàng: stackoverflow.com/a/58619985/1617857
Léo Benoist

54

nếu bạn arrayđược xây dựng từ truy vấn cơ sở dữ liệu, bạn có thể thay đổi khóa trực tiếp từ mysqlcâu lệnh:

thay vì

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

sử dụng một cái gì đó như:

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

Câu trả lời tuyệt vời, rất có giá trị!
DevMoutarde

20

Câu trả lời từ KernelM rất hay, nhưng để tránh vấn đề được Greg nêu ra trong phần bình luận (khóa xung đột), sử dụng một mảng mới sẽ an toàn hơn

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

Đây là một giải pháp tốt, miễn là mảng của bạn có kích thước hợp lý. Nếu mảng của bạn tiêu thụ hơn một nửa bộ nhớ PHP có sẵn, điều này sẽ không hoạt động.
kingjeffrey

12
@kingjeffrey, không hẳn. Các giá trị mảng sẽ không được sao chép miễn là chúng "chỉ được sao chép" mà không bị sửa đổi. Ví dụ, nếu có một mảng chứa 10'000 yếu tố và tiêu thụ bộ nhớ 40MB, sao chép nó sẽ tiêu thụ bộ nhớ đó là cần thiết để lưu trữ 10'000 chỉ tham chiếu đến các giá trị đã tồn tại chứ không phải là bản sao của các giá trị , vì vậy nếu 1 mảng tiêu thụ 40MB, sao chép nó có thể tiêu thụ khoảng 0,5 MB (đã thử nghiệm).
binaryLV

17

Bạn có thể sử dụng một mảng kết hợp thứ hai ánh xạ các tên người có thể đọc được thành id. Điều đó cũng sẽ cung cấp một mối quan hệ Nhiều đến 1. Sau đó làm một cái gì đó như thế này:

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

11

Nếu bạn cũng muốn vị trí của khóa mảng mới giống với vị trí cũ, bạn có thể làm điều này:

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

7

Nếu mảng của bạn được đệ quy, bạn có thể sử dụng chức năng này: kiểm tra dữ liệu này:

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

đây là chức năng:

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

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

3
Tôi yêu tôi chức năng mảng của tôi. Tôi đã đề nghị đây là một lớp lót đẹp để đổi tên tất cả các khóa và duy trì thứ tự mảng, nhưng tôi sẽ đề nghị thay thế cho bạn.
Mùa thu Leonard

6

Tôi thích giải pháp của KernelM, nhưng tôi cần một cái gì đó sẽ xử lý các xung đột khóa tiềm ẩn (trong đó một khóa mới có thể khớp với khóa hiện tại). Đây là những gì tôi đã đưa ra:

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

Sau đó, bạn có thể chuyển qua một mảng như thế này:

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

6

Đây là một chức năng trợ giúp để đạt được điều đó:

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

khá dựa trên câu trả lời @KernelM .

Sử dụng:

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

Nó sẽ trả về true khi đổi tên thành công, nếu không thì sai .


Xin lưu ý rằng điều này làm thay đổi thứ tự của mảng (phần tử của khóa được đổi tên sẽ ở cuối mảng, không ở cùng vị trí trong mảng như ban đầu). Ngoài ra, tôi thường không bắt đầu một tên hàm với dấu gạch dưới (theo truyền thống được sử dụng để chỉ định các chức năng sử dụng nội bộ đặc biệt).
orrd

4

Công cụ dễ dàng:

hàm này sẽ chấp nhận mục tiêu $ hash và thay thế $ cũng là hàm băm chứa newkey => liên kết oldkey .

Hàm này sẽ duy trì thứ tự ban đầu , nhưng có thể có vấn đề đối với các mảng rất lớn (như các bản ghi trên 10k) liên quan đến hiệu suất & bộ nhớ .

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

chức năng thay thế này sẽ làm tương tự, với hiệu suất và sử dụng bộ nhớ tốt hơn nhiều , với chi phí mất đơn hàng ban đầu (không phải là vấn đề vì nó có thể băm!)

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

4

mã này sẽ giúp thay đổi oldkey thành cái mới

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

hiển thị như

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

3

So sánh điểm chuẩn đơn giản của cả hai giải pháp.

Giải pháp 1 Sao chép và xóa (mất đơn hàng) https://stackoverflow.com/a/240676/1617857

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

Giải pháp 2 Đổi tên khóa 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 );
}

Các kết quả:

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

2

Bạn có thể sử dụng chức năng này dựa trên mảng_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));

Nó cho:

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

1

cái này hoạt động để đổi tên khóa đầu tiên:

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

sau đó, print_r ($ a) biểu hiện một mảng theo thứ tự đã sửa chữa:

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

cái này hoạt động để đổi tên một khóa tùy ý:

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

một hàm tổng quát:

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

    return array_flip($tmp_A);
}

1

Nếu bạn muốn thay thế một số khóa cùng một lúc (giữ trật tự):

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

Sử dụng:

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

1

Có một cách khác để thay đổi khóa của một phần tử mảng khi làm việc với một mảng đầy đủ - mà không thay đổi thứ tự của mảng. Nó chỉ đơn giản là sao chép mảng vào một mảng mới.

Chẳng hạn, tôi đã làm việc với một mảng hỗn hợp, đa chiều có chứa các khóa được lập chỉ mục và liên kết - và tôi muốn thay thế các khóa số nguyên bằng các giá trị của chúng, mà không phá vỡ thứ tự.

Tôi đã làm như vậy bằng cách chuyển khóa / giá trị cho tất cả các mục mảng số - tại đây: ['0' => 'foo']. Lưu ý rằng thứ tự còn nguyên vẹn.

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

Đầu ra:

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

1

cách tốt nhất là sử dụng tham chiếu và không sử dụng unset (điều này tạo ra một bước khác để làm sạch bộ nhớ)

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

giải pháp:

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

bạn có một bản gốc và một tài liệu tham khảo với tên mới.

hoặc nếu bạn không muốn có hai tên trong một giá trị thì hãy tạo một tab khác và thảo luận về tham chiếu

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

Lặp lại tốt hơn trên các khóa hơn là sao chép tất cả các mảng và làm sạch mảng cũ nếu bạn có dữ liệu dài như 100 hàng +++, v.v.


0

Hmm, tôi không thử nghiệm trước đây, nhưng tôi nghĩ mã này hoạt động

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

Json mã hóa và giải mã? Đây là một câu trả lời thực sự xấu.
kixorz

0

Một trong đó bảo lưu đơn đặt hàng đó là dễ hiểu:

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

0

Bạn có thể viết hàm đơn giản áp dụng gọi lại cho các phím của mảng đã cho. Tương tự như mảng_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}}

Đây là một ý chính https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php .


0

Hàm này sẽ đổi tên một khóa mảng, giữ nguyên vị trí của nó, bằng cách kết hợp với tìm kiếm chỉ mục.

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

Sử dụng:

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

-1

Hàm cơ bản này xử lý các khóa mảng và giữ mảng theo thứ tự ban đầu ...

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

Sau đó, bạn có thể lặp qua và trao đổi tất cả các phím 'a' với 'z' chẳng hạn ...

$inputs = [
  0 => ['a'=>'1','b'=>'2'],
  1 => ['a'=>'3','b'=>'4']
]

$keySwap = ['a'=>'z'];

foreach($inputs as $k=>$i){
    $inputs[$k] = $this->keySwap($i,$keySwap);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.