2012-01-16 20 views
18

Puede "change" the key of an array element simplemente mediante el establecimiento de la nueva clave y la eliminación de la antigua cambiante:Cambio clave de la matriz sin fin

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

Pero esto va a mover la llave de la final de la matriz.

¿Hay alguna forma elegante de cambiar la llave sin cambiar el orden?

(PS:. Esta pregunta es sólo por interés conceptual, no porque lo necesite en cualquier lugar)

+0

Imagino que algún constructo feo con array_splice() y array_slice() haría el truco –

+0

@MarcB Aunque eso no funcionaría con las claves de cadena. – NikiC

+0

No soy un programador PHP, pero ¿qué hay en el mundo con la semántica de '$ arr [$ oldKey]' si esto funciona como un argumento para una función que elimina '$ oldKey' de' $ arr'? Creo que PHP podría ser más interesante de lo que creía, tendrá que investigar esto ... –

Respuesta

25

probado y funciona :)

$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 Aunque probablemente debas agregar un controlador de errores para el caso que '$ old_key' no esté en la matriz. –

+0

Solo si la clave no existe, reemplace la primera. Agregue una cláusula if, y está bien;) – Kristian

+0

¿No sería mejor devolver la matriz sin cambios en lugar de lanzar una excepción? –

-1

hacen una doble flip! Al menos eso es todo lo que puedo pensar:

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

Y esto es solo teoría, no he probado para ver si funciona, pero me imagino que sí. –

+5

Eso fallará si hay valores duplicados. –

+0

Verdadero ... welp, entonces estoy sin ideas. –

6

Una forma sería utilizar simplemente una iteración foreach sobre la matriz y copiarla en una nueva matriz, cambiar la clave de forma condicional, mientras que la iteración, por ejemplo, Si $ clave === 'foo', entonces no uso, pero foo bar:

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

Otra forma sería la de serialize la matriz, str_replace la tecla serializado y luego unserialize de nuevo en una matriz de nuevo. Sin embargo, eso no es particularmente elegante y propenso a errores, especialmente cuando no solo tienes escalas o matrices multidimensionales.

Una tercera manera - mi favorito - estaría escribiendo array_key_rename en C y proponerlo para el núcleo de PHP;)

+0

¿Se puede acceder $ newArray fuera del alcance de foreach? – nawfal

+0

@nawfal sí, pero no fuera de la función a menos que asigne el valor de retorno – Gordon

+0

OK. Es extraño acostumbrarse a PHP proveniente de otro idioma :) – nawfal

-2

Usted podría utilizar array_combine. Se combina una matriz para las claves y otra para los valores ...

Por ejemplo:

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

¿Qué pasa si tienes muchas llaves y quieres cambiar solo una? Con su solución, se vería obligado a escribir una matriz interminable de $ new_keys. –

9

Algo como esto también puede funcionar:

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

SALIDA:

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

¡Personalmente encuentro esta solución muy elegante! +1 –

+3

Yo también. Esto funciona de maravilla para eliminar guiones/guiones bajos de nombres de etiquetas XML cuando se usa Zend_Config_XML :: toArray(). En mi caso, los datos son opciones para elementos seleccionados con grupos optg. Los nombres de mi grupo de opciones eran etiquetas XML y los títulos tenían guiones. Esto funcionó bien para eso. – axiom82

+3

No me parece elegante. Muy peligrosa. – nawfal

0

Estamos utilizando esta función para cambiar varias teclas de matriz dentro de un a RRay mantener el orden:

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

Puede pasar un array como $ keys_map, así:

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

Esta solución se basa en una Kristian.

Cuestiones relacionadas