Jak w PHP zmienić klucz elementu tablicy?


348

Mam tablicę asocjacyjną w postaci, w key => valuektórej klucz jest wartością liczbową, jednak nie jest to kolejna wartość liczbowa. Klucz jest w rzeczywistości numerem identyfikacyjnym, a wartość jest liczbą. W większości przypadków jest to w porządku, jednak potrzebuję funkcji, która pobiera czytelną dla człowieka nazwę tablicy i używa jej dla klucza, bez zmiany wartości.

Nie widziałem funkcji, która to robi, ale zakładam, że muszę podać stary klucz i nowy klucz (oba mam) i przekształcić tablicę. Czy istnieje skuteczny sposób na zrobienie tego?


Odpowiedzi:


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

5
Uważaj tylko: 1) Żadne dwa klucze nie mają tej samej wersji czytelnej dla człowieka 2) Żadne wersje czytelne dla człowieka nie są cyframi
Greg

81
Prawdopodobnie zmieniłoby to również kolejność tablic, o których być może trzeba będzie uważać. Nawet tablice asocjacyjne w PHP są uporządkowane, a czasami ta kolejność jest wykorzystywana.
Robin Winslow

7
Tak, świetna uwaga Robin. Czy istnieje sposób na utrzymanie tego samego porządku? A może musisz stworzyć nową tablicę, aby to osiągnąć?
Simon East

40
Pytanie dodatkowe: jak zmienić identyfikator, ale zachować kolejność tablic?
Petr Peller,

17
jeśli wartość klucza się nie zmienia, usuniesz element tablicy. Możesz to sprawdzić.
Peeech,

97

Aby to zrobić i zachować porządek w tablicy, należy umieścić klucze tablicy w osobnej tablicy, znaleźć i wymienić klucz w tej tablicy, a następnie połączyć go z wartościami.

Oto funkcja, która właśnie to robi:

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
Dzięki temu było to bardzo pomocne, ponieważ musiałem zachować porządek w tablicy. Próbowałem już zaakceptowanej odpowiedzi, zanim znalazłem tę stronę.
gillytech

3
Tak, wolę zachować porządek w tablicy, wygląda ładniej.
Phil Cook

2
Musiałem zachować kluczowy porządek, dobry, działał jak urok!
Uczeń

Nieważne, czy chcesz występy lub zachować zamówienie: stackoverflow.com/a/58619985/1617857
Léo Benoist

54

jeśli twoja arrayjest zbudowana z zapytania do bazy danych, możesz zmienić klucz bezpośrednio z mysqlinstrukcji:

zamiast

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

użyj czegoś takiego jak:

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

świetna odpowiedź, bardzo cenna!
DevMoutarde

20

Odpowiedź z KernelM jest miła, ale aby uniknąć problemu podniesionego przez Grega w komentarzu (konflikt kluczy), użycie nowej tablicy byłoby bezpieczniejsze

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

To dobre rozwiązanie, pod warunkiem, że macierz ma rozsądny rozmiar. Jeśli tablica zużywa ponad połowę dostępnej pamięci PHP, to nie zadziała.
kingjeffrey

12
@kingjeffrey, niezupełnie. Wartości tablicowe nie będą duplikowane, dopóki zostaną „tylko skopiowane” bez modyfikacji. Na przykład, jeśli istnieje jedna tablica, która zawiera 10 000 elementów i zużywa 40 MB pamięci, skopiowanie jej zajmie pamięć potrzebną do przechowywania 10 000 tylko odniesień do już istniejących wartości zamiast kopii wartości , więc jeśli 1 tablica zużywa 40 MB, jej kopia może zużywać może 0,5 MB (testowane).
binaryLV

17

Możesz użyć drugiej tablicy asocjacyjnej, która mapuje czytelne dla ludzi nazwy na id. Zapewniłoby to również relację wiele do jednego. Następnie zrób coś takiego:

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

11

Jeśli chcesz, aby położenie nowego klucza tablicy było takie samo jak starego, możesz to zrobić:

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

Jeśli tablica jest rekurencyjna, możesz użyć tej funkcji: przetestuj te dane:

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

oto funkcja:

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
Uwielbiam moje funkcje tablicowe. Właśnie miałem zasugerować to jako fajny jednowierszowy program do zmiany nazw wszystkich kluczy i utrzymania kolejności tablic, ale zamiast tego polecę twój.
Jesień Leonard

6

Lubię rozwiązanie KernelM, ale potrzebowałem czegoś, co poradziłoby sobie z potencjalnymi konfliktami kluczy (gdzie nowy klucz może pasować do istniejącego klucza). Oto, co wymyśliłem:

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

Następnie możesz przewijać tablicę w następujący sposób:

$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

Oto funkcja pomocnika, aby to osiągnąć:

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

całkiem na podstawie odpowiedzi @KernelM .

Stosowanie:

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

Zwróci true po udanej zmianie nazwy, w przeciwnym razie false .


Należy pamiętać, że zmienia to kolejność tablicy (element klucza o zmienionej nazwie będzie na końcu tablicy, a nie w tej samej pozycji w tablicy, w jakiej był pierwotnie). Poza tym zwykle nie zaczynam nazwy funkcji znakiem podkreślenia (tradycyjnie używanym do oznaczania specjalnych funkcji użytku wewnętrznego).
2016 r.

4

Proste rzeczy:

ta funkcja zaakceptuje docelowy skrót $, a $ zamienniki to również skrót zawierający powiązania newkey => oldkey .

Ta funkcja zachowuje pierwotną kolejność , ale może być problematyczna w przypadku bardzo dużych (jak powyżej 10 000 rekordów) tablic dotyczących wydajności i pamięci .

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

ta alternatywna funkcja zrobiłaby to samo, przy znacznie lepszej wydajności i zużyciu pamięci, kosztem utraty oryginalnego zamówienia (co nie powinno stanowić problemu, ponieważ jest 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;       
}

4

ten kod pomoże zmienić stary klucz na nowy

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

wyświetlać się jak

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

3

Proste porównanie wyników obu rozwiązań.

Rozwiązanie 1 Skopiuj i usuń (zamówienie utracone) https://stackoverflow.com/a/240676/1617857

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

Rozwiązanie 2 Zmień nazwę klucza 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 );
}

Wyniki:

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

Możesz użyć tej funkcji w oparciu o 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));

To daje:

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

działa to na zmianę nazwy pierwszego klucza:

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

następnie print_r ($ a) renderuje naprawioną tablicę w kolejności:

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

działa to na zmianę nazwy dowolnego klucza:

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

uogólniona funkcja:

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

    return array_flip($tmp_A);
}

1

Jeśli chcesz wymienić kilka kluczy jednocześnie (zachowując porządek):

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

Stosowanie:

$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

Istnieje alternatywny sposób zmiany klucza elementu tablicy podczas pracy z pełną tablicą - bez zmiany kolejności tablicy. Po prostu skopiuj tablicę do nowej tablicy.

Na przykład pracowałem z mieszaną, wielowymiarową tablicą, która zawierała indeksowane i asocjacyjne klucze - i chciałem zastąpić klucze liczb całkowitych ich wartościami, nie przerywając kolejności.

Zrobiłem to, zmieniając klucz / wartość dla wszystkich wpisów tablicy numerycznej - tutaj: ['0' => 'foo']. Pamiętaj, że zamówienie jest nienaruszone.

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

Wynik:

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

1

najlepszym sposobem jest użycie referencji, a nie użycie nieustawionych (co stanowi kolejny krok do wyczyszczenia pamięci)

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

rozwiązanie:

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

masz jeden oryginał i jedno odniesienie z nową nazwą.

lub jeśli nie chcesz, aby dwie nazwy w jednej wartości były dobre, zrób inną zakładkę i wypowiedz na wszelki wypadek

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

Iterracja jest lepsza dla kluczy niż klonowanie całej tablicy i czyszczenie starej tablicy, jeśli masz długie dane, takie jak 100 wierszy +++ itp.


0

Hmm, nie testuję wcześniej, ale myślę, że ten kod działa

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 koduje i dekoduje? To jest naprawdę zła odpowiedź.
kixorz

0

Taki, który zamówienia preserverów są łatwe do zrozumienia:

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

Możesz napisać prostą funkcję, która stosuje wywołanie zwrotne do klawiszy danej tablicy. Podobne do 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}}

Oto sedno https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php .


0

Ta funkcja zmieni nazwę klucza tablicy, zachowując jego pozycję, łącząc się z wyszukiwaniem indeksów.

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

Stosowanie:

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

-1

Ta podstawowa funkcja obsługuje zamianę klawiszy tablicy i utrzymanie tablicy w oryginalnej kolejności ...

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

Możesz następnie przejść przez pętlę i zamienić wszystkie klucze „a” na „z” na przykład ...

$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);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.