2012-01-16 2 views
18

Vous pouvez "change" the key of an array element simplement en définissant la nouvelle clé et le retrait du vieux:changement clé du tableau sans changer l'ordre

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

Mais cela déplacera la clé à la fin du tableau.

Existe-t-il une manière élégante de changer la clé sans changer l'ordre?

(PS:. Cette question est juste de l'intérêt conceptuel, non pas parce que j'ai besoin partout)

+0

J'imagine que quelque construction moche avec array_splice() et array_slice() ferait l'affaire –

+0

@MarcB Cela ne fonctionnerait pas avec les clés de chaîne bien que. – NikiC

+0

Je ne suis pas un programmeur PHP, mais dans le monde, quelle est la sémantique de '$ arr [$ oldKey]' si cela fonctionne comme argument d'une fonction qui supprime '$ oldKey' de' $ arr'? Je pense que PHP pourrait être plus intéressant que je ne le pensais auparavant, devra se pencher sur cela ... –

Répondre

25

testé et fonctionne :)

$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 Bien que vous deviez probablement ajouter un gestionnaire d'erreur dans le cas où '$ old_key' n'est pas dans le tableau. –

+0

Seulement si la clé n'existe pas, remplacez la première. Ajoutez une clause if, et vous êtes d'accord;) – Kristian

+0

Ne serait-il pas préférable de retourner le tableau inchangé au lieu de lancer une exception? –

-1

faire une double bascule! Au moins c'est tout ce que je peux penser à:

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

Et c'est juste de la théorie, je n'ai pas testé pour voir si cela fonctionne, mais j'imagine que ce serait le cas. –

+5

Cela échouera s'il existe des valeurs en double. –

+0

Vrai .... welp, alors je suis à court d'idées. –

6

Une façon serait d'utiliser simplement un itérer foreach sur le tableau et le copier dans un nouveau tableau, en changeant la clé sous condition tout en réitérant, par exemple si « foo » clés $ === alors n'utilisez foo mais bar:

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

Une autre façon serait de serialize le tableau, str_replace la clé sérialisé puis unserialize de nouveau dans un tableau à nouveau. Ce n'est pas particulièrement élégant et probablement sujettes aux erreurs, surtout lorsque vous n'avez pas seulement des scalaires ou des tableaux multidimensionnels.

Une troisième voie - mon préféré - vous seriez en train d'écrire array_key_rename en C et en proposant pour le noyau de PHP;)

+0

$ newArray est-il accessible depuis l'extérieur de foreach? – nawfal

+0

@nawfal oui, mais pas en dehors de la fonction, sauf si vous affectez la valeur de retour – Gordon

+0

OK. Bit étrange pour s'habituer à PHP venant d'une autre langue :) – nawfal

-2

Vous pouvez utiliser array_combine. Il fusionne un tableau pour les clés et une autre pour les valeurs ...

Par exemple:

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

Que faire si vous avez beaucoup de nombreuses clés et que vous voulez en changer un seul? Avec votre solution, vous seriez obligé d'écrire un tableau sans fin $ new_keys. –

9

Quelque chose comme cela peut aussi fonctionner:

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

SORTIE:

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

Personnellement, je trouve cette solution très élégante! +1 –

+3

Moi aussi. Cela fonctionne merveilleusement pour enlever des tirets/underscores des noms de balise XML en utilisant Zend_Config_XML :: toArray(). Dans mon cas, les données sont des options pour sélectionner des éléments w/optgroups. Mes noms optgroup étaient des balises XML et les titres avaient des tirets. Cela a bien fonctionné pour cela. – axiom82

+3

Je ne trouve pas cet élégant. Très dangereux. – nawfal

0

Nous utilisons cette fonction pour changer plusieurs clés de tableau dans un rray maintenir l'ordre:

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

Vous pouvez passer un tableau comme keys_map $, comme ceci:

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

Cette solution est basée sur Kristian un.

Questions connexes