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?

Thomas Owens
źródło
Zobacz podobne stackoverflow.com/q/308703
Peter Krauss

Odpowiedzi:

576
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
Jądro
źródło
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 );
}
DiverseAndRemote.com
źródło
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´..."
Simon Franco
źródło
ś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);
kjg
źródło
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']];
Tom Ritter
źródło
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;
}
spreadzz
źródło
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;   
}
pajafumo
źródło
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
źródło
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' )
Kingjeffrey
źródło
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 .

kenorb
źródło
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;       
}
Nadir
źródło
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");
karthikeyan ganesan
źródło
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
Léo Benoist
źródło
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
    )
)
Aleksander
źródło
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);
}
wmmso
źródło
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);
lepe
źródło
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
        )
)
Kristoffer Bohmann
źródło
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.

Kamil Dąbrowski
źródło
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);
}
Frank Vu
źródło
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;
}
Andrzej
źródło
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 .

vardius
źródło
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');
Dotacja
źródło
-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);
}
MikeyJ
źródło