2012-01-16 12 views
18

È possibile "change" the key of an array element semplicemente impostando la nuova chiave e la rimozione del vecchio che cambia:Change chiave array senza fine

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

Ma questo si muoverà la chiave per la fine della matrice.

C'è un modo elegante per cambiare la chiave senza cambiare l'ordine?

(PS:. Questa domanda è solo per interesse concettuale, non perché ne ho bisogno ovunque)

+0

Immagino un qualche brutto costrutto con array_splice() e array_slice() farebbe il trucco –

+0

@MarcB che però non funzionerebbe con le chiavi di stringa. – NikiC

+0

Non sono un programmatore PHP, ma quali sono al mondo la semantica di '$ arr [$ oldKey]' se funziona come argomento per una funzione che rimuove '$ oldKey' da' $ arr'? Penso che PHP potrebbe essere più interessante di quanto pensassi in precedenza, dovrò esaminare questo ... –

risposta

25

provato ed impianti :)

$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 Anche se probabilmente dovresti aggiungere un gestore di errori per il caso che '$ old_key' non è nell'array. –

+0

Solo se la chiave non esiste, sostituire la prima. Aggiungi una clausola if, e stai ok;) – Kristian

+0

Non sarebbe meglio restituire la matrice invariata invece di lanciare un'eccezione? –

-1

fare un doppio flip! Almeno questo è tutto quello che posso pensare:

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

E questa è solo teoria, non ho provato a vedere se funziona, ma immagino lo farebbe. –

+5

Questo fallirà se ci sono valori duplicati. –

+0

Vero .... welp, quindi sono fuori di idee. –

6

Un modo sarebbe di usare semplicemente un iterazione foreach sopra la matrice e copiandolo in un nuovo array, modificando la chiave condizionalmente, mentre l'iterazione, ad esempio, Se $ === chiave 'pippo' allora non utilizzare foo ma bar:

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

Un altro modo sarebbe quello di serialize la matrice, str_replace la chiave serializzato e poi unserialize di nuovo in un array di nuovo. Questo non è particolarmente elegante e probabilmente incline agli errori, specialmente quando non si hanno solo scalari o array multidimensionali.

Un terzo modo - il mio preferito - sarebbe scrivendo array_key_rename in C e proporlo per il nucleo di PHP;)

+0

$ NewArray è accessibile dall'esterno di foreach? – nawfal

+0

@nawfal yes, ma non al di fuori della funzione a meno che non si assegni il valore restituito – Gordon

+0

OK. Un po 'strano da abituare a PHP proveniente da un'altra lingua :) – nawfal

-2

Si potrebbe utilizzare array_combine. Si fonde un array per le chiavi e un altro per i valori ...

Ad esempio:

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

e se hai molte chiavi e vuoi cambiarne solo una? Con la tua soluzione sarai obbligato a scrivere una serie infinita di $ new_keys. –

9

Qualcosa di simile può anche funzionare:

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

OUTPUT:

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

Personalmente trovo questa soluzione molto elegante! +1 –

+3

Anch'io. Questo funziona meravigliosamente per rimuovere trattini/caratteri di sottolineatura dai nomi dei tag XML quando si utilizza Zend_Config_XML :: toArray(). Nel mio caso, i dati sono opzioni per gli elementi selezionati w/optgroups. I miei nomi optgroup erano tag XML e i titoli avevano dei trattini. Questo ha funzionato bene per questo. – axiom82

+3

Non lo trovo elegante. Molto pericoloso. – nawfal

0

Si sta utilizzando questa funzione per modificare più chiavi di array all'interno di un RRay mantenere l'ordine:

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

È possibile passare una matrice da $ keys_map, in questo modo:

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

Questa soluzione si basa su Kristian uno.