2012-01-16 16 views
18

Można "change" the key of an array element poprzez ustawienie nowego klucza i usuwanie starych zmienia:Zmień klucz tablicy bez zlecenia

$array[$newKey] = $array[$oldKey]; 
unset($array[$oldKey]); 

Ale to będzie przenieść klucz do końca tablicy.

Czy istnieje jakiś elegancki sposób na zmianę klucza bez zmiany zamówienia?

(PS. To pytanie jest tylko z koncepcyjnego zainteresowania, bo nie muszę go w dowolnym miejscu)

+0

Wyobrażam sobie, że niektóre brzydkie konstrukcje z array_splice() i array_slice() mogłyby zrobić lewę –

+0

@MarcB To nie działałoby jednak z kluczami łańcuchowymi. – NikiC

+0

Nie jestem programistą PHP, ale co na świecie jest semantyką '$ arr [$ oldKey]' jeśli działa to jako argument funkcji, która usuwa '$ oldKey' z' $ arr'? Myślę, że PHP może być ciekawsze, niż wcześniej sądziłem, będzie musiał przyjrzeć się temu ... –

Odpowiedz

25

Przetestowane i działa :)

$array = array("a" => "1", "b" => "2", "c" => "3"); 

function replace_key($array, $old_key, $new_key) { 
    $keys = array_keys($array); 
    if (false === $index = array_search($old_key, $keys)) { 
     throw new Exception(sprintf('Key "%s" does not exit', $old_key)); 
    } 
    $keys[$index] = $new_key; 
    return array_combine($keys, array_values($array)); 
} 

$new_array = replace_key($array, "b", "e"); 
+0

+1 Chociaż prawdopodobnie powinieneś dodać obsługę błędu dla sprawy, że '$ old_key' nie znajduje się w tablicy. –

+0

Tylko jeśli klucz nie istnieje, należy wymienić pierwszy. Dodaj klauzulę if, a wszystko w porządku;) – Kristian

+0

Czy nie lepiej powrócić do niezmienionej tablicy, zamiast rzucać wyjątek? –

-1

Czy podwójne salto! Przynajmniej to jest wszystko, co mogę myśleć:

$array=("foo"=>"bar","asdf"=>"fdsa"); 
$array=array_flip($array); 
$array["bar"]=>'newkey'; 
$array=array_flip($array); 
+0

A to tylko teoria, nie testowałem, żeby sprawdzić, czy to działa, ale wyobrażam sobie, że tak. –

+5

To się nie powiedzie, jeśli istnieją zduplikowane wartości. –

+0

Prawda .... welp, a potem brak mi pomysłów. –

6

Jednym ze sposobów byłoby po prostu użyć Iterowanie foreach na tablicy i skopiowanie go do nowej tablicy, zmieniając klucz warunkowo podczas iteracji, np jeśli $ key === 'foo', to nie używaj foo ale bar:

function array_key_rename($array, $oldKey, $newKey) 
{ 
    $newArray = []; 
    foreach ($array as $key => $value) { 
     $newArray[$key === $oldKey ? $newKey : $key] = $value; 
    } 
    return $newArray; 
} 

Innym sposobem byłoby serialize tablicy str_replace klawisz odcinkach, a następnie unserialize powrotem do tablicy ponownie. To nie jest szczególnie eleganckie i prawdopodobnie podatne na błędy, zwłaszcza gdy nie masz tylko skalarów lub tablic wielowymiarowych.

Trzeci sposób - mój ulubiony - byłby piszesz array_key_rename w C i proponuje go do rdzenia PHP;)

+0

Czy usługa $ newArray jest dostępna spoza zakresu foreach? – nawfal

+0

@nawfal tak, ale nie poza funkcją, chyba że przypiszesz wartość zwrotu – Gordon

+0

OK. Trochę dziwne, żeby przyzwyczaić się do PHP pochodzącego z innego języka :) – nawfal

-2

Można użyć array_combine. Łączy on w sobie tablicę kluczy a drugiej dla wartości ...

Na przykład:

$original_array =('foo'=>'bar','asdf'=>'fdsa'); 
$new_keys  = array('abc', 'def'); 
$new_array  = array_combine($new_keys, $original_array); 
+0

co, jeśli masz wiele kluczy i chcesz zmienić tylko jeden? Dzięki twojemu rozwiązaniu będziesz zobowiązany do napisania niekończącej się tablicy $ new_keys. –

9

Coś takiego może również działać:

$langs = array("EN" => "English", 
     "ZH" => "Chinese", 
     "DA" => "Danish", 
     "NL" => "Dutch", 
     "FI" => "Finnish", 
     "FR" => "French", 
     "DE" => "German"); 
$json = str_replace('"EN":', '"en":', json_encode($langs)); 
print_r(json_decode($json, true)); 

wyjściowa:

Array 
(
    [en] => English 
    [ZH] => Chinese 
    [DA] => Danish 
    [NL] => Dutch 
    [FI] => Finnish 
    [FR] => French 
    [DE] => German 
) 
+6

Osobiście uważam to rozwiązanie za bardzo eleganckie! +1 –

+3

Ja też. Działa to wspaniale przy usuwaniu kresek/podkreśleń z nazw znaczników XML podczas używania Zend_Config_XML :: toArray(). W moim przypadku dane są opcjami dla wybranych elementów w/optgroups. Moje nazwy grup dyskusyjnych były znacznikami XML, a tytuły zawierały kreski. To zadziałało dobrze. – axiom82

+3

Nie uważam tego za eleganckie. Bardzo niebezpieczne. – nawfal

0

Używamy tej funkcji do zmiany wielu kluczy tablic w ciągu rray zachowując kolejność:

function replace_keys($array, $keys_map) { 
    $keys = array_keys($array); 
    foreach($keys_map as $old_key=>$new_key){ 
     if (false === $index = array_search($old_key, $keys)) { 
      continue; 
     } 
     $keys[$index] = $new_key; 
    } 
    return array_combine($keys, array_values($array)); 
} 

można przekazać tablicę jako $ keys_map coś takiego:

$keys_map=array("old_key_1"=>"new_key_1", "old_key_2"=>"new_key_2",...) 

Rozwiązanie to jest oparte na Kristian jednym.

Powiązane problemy