Di PHP, bagaimana Anda mengubah kunci elemen array?

348

Saya memiliki array asosiatif dalam bentuk di key => valuemana kunci adalah nilai numerik, namun itu bukan nilai numerik berurutan. Kuncinya sebenarnya adalah nomor ID dan nilainya adalah hitungan. Ini bagus untuk sebagian besar contoh, namun saya ingin fungsi yang mendapatkan nama array yang dapat dibaca manusia dan menggunakannya untuk kuncinya, tanpa mengubah nilainya.

Saya tidak melihat fungsi yang melakukan ini, tapi saya berasumsi saya perlu memberikan kunci lama dan kunci baru (keduanya saya miliki) dan mengubah array. Apakah ada cara yang efisien untuk melakukan ini?

Thomas Owens
sumber
Lihat stackoverflow.com/q/308703 yang
Peter Krauss

Jawaban:

576
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
KernelM
sumber
5
Berhati-hatilah bahwa 1) Tidak ada dua kunci yang memiliki versi yang dapat dibaca manusia yang sama 2) Tidak ada versi yang dapat dibaca manusia yang kebetulan berupa angka
Greg
81
Juga ini mungkin akan mengubah urutan array, yang mungkin perlu Anda perhatikan. Bahkan array asosiatif dalam PHP diperintahkan, dan kadang-kadang urutan itu dimanfaatkan.
Robin Winslow
7
Ya, bagus, Robin. Apakah ada cara untuk menjaga urutan yang sama? Atau apakah Anda perlu membuat array baru untuk mencapainya?
Simon East
40
Pertanyaan bonus: Bagaimana cara mengubah ID, tetapi tetap mempertahankan susunan array?
Petr Peller
17
jika nilai kunci tidak berubah, Anda akan menghapus elemen array. Anda mungkin ingin memeriksanya.
Peeech
97

Cara Anda melakukan ini dan mempertahankan urutan array adalah dengan meletakkan kunci array ke dalam array yang terpisah, menemukan dan mengganti kunci dalam array itu dan kemudian menggabungkannya kembali dengan nilai-nilai.

Berikut adalah fungsi yang melakukan hal itu:

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 );
}
DiverseAndRemote.com
sumber
2
Terima kasih ini sangat membantu karena saya perlu menjaga urutan array. Saya sudah mencoba jawaban yang diterima sebelum saya menemukan halaman ini.
gillytech
3
Ya lebih suka menjaga urutan array, terlihat lebih rapi.
Phil Cook
2
Harus menjaga urutan kunci, bagus, bekerja seperti pesona!
Pelajar
Keberatan jika Anda ingin pertunjukan atau pelestarian pesanan: stackoverflow.com/a/58619985/1617857
Léo Benoist
54

jika Anda arraydibuat dari kueri basis data, Anda dapat mengubah kunci langsung dari mysqlpernyataan:

dari pada

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

gunakan sesuatu seperti:

"select ´id´ **as NEWNAME** from ´tablename´..."
Simon Franco
sumber
jawaban yang bagus, sangat berharga!
DevMoutarde
20

Jawaban dari KernelM bagus, tetapi untuk menghindari masalah yang diangkat oleh Greg di komentar (kunci yang bertentangan), menggunakan array baru akan lebih aman

$newarr[$newkey] = $oldarr[$oldkey];
$oldarr=$newarr;
unset($newarr);
kjg
sumber
Ini adalah solusi yang baik, asalkan ukuran array Anda masuk akal. Jika array Anda menggunakan lebih dari setengah memori PHP yang tersedia, ini tidak akan berfungsi.
kingjeffrey
12
@kingjeffrey, tidak juga. Nilai array tidak akan diduplikasi selama mereka "hanya disalin" tanpa dimodifikasi. Misalnya, jika ada satu array yang berisi 10'000 elemen dan menggunakan memori 40MB, menyalinnya akan menggunakan memori yang diperlukan untuk menyimpan referensi 10'000 hanya untuk nilai yang sudah ada daripada salinan nilai , jadi jika 1 array mengkonsumsi 40MB, salinannya mungkin mengkonsumsi mungkin 0,5MB (diuji).
binaryLV
17

Anda bisa menggunakan array asosiatif kedua yang memetakan nama yang dapat dibaca manusia ke id. Itu juga akan memberikan hubungan Banyak ke 1. Kemudian lakukan sesuatu seperti ini:

echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];
Tom Ritter
sumber
11

Jika Anda ingin juga posisi kunci array baru sama dengan yang lama Anda dapat melakukan ini:

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

Jika array Anda bersifat rekursif, Anda dapat menggunakan fungsi ini: uji data ini:

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

di sini adalah fungsinya:

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;   
}
pajafumo
sumber
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
];
*/
temuri
sumber
3
Saya suka saya fungsi array saya. Saya akan menyarankan ini sebagai one-liner yang bagus untuk mengubah nama semua kunci dan mempertahankan susunan array, tetapi saya akan merekomendasikan milik Anda sebagai gantinya.
Autumn Leonard
6

Saya suka solusi KernelM, tetapi saya membutuhkan sesuatu yang akan menangani potensi konflik kunci (di mana kunci baru mungkin cocok dengan kunci yang ada). Inilah yang saya pikirkan:

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

Anda kemudian dapat menggilir array seperti ini:

$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' )
kingjeffrey
sumber
6

Berikut adalah fungsi pembantu untuk mencapainya:

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

cukup berdasarkan jawaban @KernelM .

Pemakaian:

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

Ini akan mengembalikan true pada penggantian nama yang sukses, jika tidak palsu .

kenorb
sumber
Ketahuilah bahwa ini mengubah urutan array (elemen kunci yang diubah namanya akan berada di akhir array, bukan pada posisi yang sama dalam array seperti aslinya). Juga saya biasanya tidak akan memulai nama fungsi dengan garis bawah (yang secara tradisional digunakan untuk menunjuk fungsi penggunaan internal khusus).
orrd
4

Hal yang mudah:

fungsi ini akan menerima target $ hash dan $ replacements juga merupakan hash yang mengandung asosiasi newkey => oldkey .

Fungsi ini akan mempertahankan orde asli , tetapi bisa bermasalah untuk array yang sangat besar (seperti catatan 10k di atas) mengenai kinerja & memori .

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

fungsi alternatif ini akan melakukan hal yang sama, dengan kinerja & penggunaan memori yang jauh lebih baik , dengan biaya kehilangan pesanan asli (yang seharusnya tidak menjadi masalah karena hashtable!)

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;       
}
Nadir
sumber
4

kode ini akan membantu untuk mengubah kunci lama ke yang baru

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

tampilan suka

$keys_array=array("one"=>"one","two"=>"two");
ganesan karthikeyan
sumber
3

Perbandingan tolok ukur sederhana dari kedua solusi.

Solusi 1 Salin dan hapus (pesanan hilang) https://stackoverflow.com/a/240676/1617857

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

Solusi 2 Ubah nama kunci 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 );
}

Hasil:

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
Léo Benoist
sumber
2

Anda dapat menggunakan fungsi ini berdasarkan 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));

Memberikan:

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
    )
)
Alekzander
sumber
1

ini berfungsi untuk mengganti nama kunci pertama:

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

kemudian, print_r ($ a) merender array berurutan yang diperbaiki:

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

ini berfungsi untuk mengganti nama kunci sewenang-wenang:

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

fungsi umum:

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

    return array_flip($tmp_A);
}
wmm
sumber
1

Jika Anda ingin mengganti beberapa kunci sekaligus (menjaga urutan):

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

Pemakaian:

$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);
lepe
sumber
1

Ada cara alternatif untuk mengubah kunci elemen array ketika bekerja dengan array penuh - tanpa mengubah urutan array. Ini hanya untuk menyalin array ke array baru.

Misalnya, saya bekerja dengan array multi-dimensi campuran yang berisi kunci yang diindeks dan asosiatif - dan saya ingin mengganti kunci integer dengan nilai-nilai mereka, tanpa melanggar urutan.

Saya melakukannya dengan mengganti kunci / nilai untuk semua entri array numerik - di sini: ['0' => 'foo']. Perhatikan bahwa pesanan masih utuh.

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

Keluaran:

Array (
    [foo] => 
    [bar] => alfa
    [baz] => Array (
            [a] => hello
            [b] => world
        )
)
Kristoffer Bohmann
sumber
1

Cara terbaik adalah menggunakan referensi, dan tidak menggunakan tidak disetel (yang membuat langkah lain untuk membersihkan memori)

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

larutan:

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

Anda memiliki satu referensi asli dan satu dengan nama baru.

atau jika Anda tidak ingin memiliki dua nama dalam satu nilai bagus buat tab lain dan pelajari referensi

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

Iterasi lebih baik pada kunci daripada mengkloning semua array, dan membersihkan array lama jika Anda memiliki data panjang seperti 100 baris +++ dll.

Kamil Dąbrowski
sumber
0

Hmm, saya tidak tes sebelumnya, tapi saya pikir kode ini berfungsi

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);
}
Frank Vu
sumber
Json mengkodekan dan mendekode? Ini jawaban yang sangat buruk.
kixorz
0

Salah satu yang dipesan oleh pengawet yang mudah dimengerti:

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;
}
Andrew
sumber
0

Anda dapat menulis fungsi sederhana yang menerapkan panggilan balik ke tombol dari array yang diberikan. Mirip dengan 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}}

Berikut adalah intinya https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php .

vardius
sumber
0

Fungsi ini akan mengubah nama kunci array, mempertahankan posisinya, dengan menggabungkan dengan pencarian indeks.

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

Pemakaian:

$arr = renameArrKey($arr, 'old_key', 'new_key');
Hibah
sumber
-1

Fungsi dasar ini menangani swapping array keys dan mempertahankan array dalam urutan aslinya ...

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

Anda kemudian dapat mengulang dan menukar semua 'a' kunci dengan 'z' misalnya ...

$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);
}
MikeyJ
sumber