Pregunta

Tengo una matriz asociativa en la forma key = > valor donde clave es un valor numérico, sin embargo, no es un valor numérico secuencial. La clave es en realidad un número de identificación y el valor es un conteo. Esto está bien para la mayoría de los casos, sin embargo, quiero una función que obtenga el nombre legible por humanos de la matriz y la use para la clave, sin cambiar el valor.

No vi una función que haga esto, pero asumo que necesito proporcionar la clave antigua y la clave nueva (ambas de las cuales tengo) y transformar la matriz. ¿Hay una forma eficiente de hacer esto?

¿Fue útil?

Solución

$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);

Otros consejos

La forma en que haría esto y preservaría el orden de la matriz es colocando las claves de la matriz en una matriz separada, busque y reemplace la clave en esa matriz y luego combínela con los valores.

Aquí hay una función que hace precisamente eso:

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

Si su array se construye a partir de una consulta de base de datos, puede cambiar la clave directamente desde la declaración de mysql :

en lugar de

"select ´id´ from ´tablename´..."

usa algo como:

"select ´id´ **as NEWNAME** from ´tablename´..."

La respuesta de KernelM es buena, pero para evitar el problema planteado por Greg en el comentario (claves en conflicto), usar una nueva matriz sería más seguro

$newarr[$newkey] = $oldarr[$oldkey];
$oldarr=$newarr;
unset($newarr);

Podría usar una segunda matriz asociativa que asigne nombres legibles por los humanos a los ID. Eso también proporcionaría una relación de Muchos a 1. Entonces haz algo como esto:

echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];

Si desea que la posición de la nueva clave de matriz sea la misma que la anterior, puede hacer esto:

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

Si su matriz es recursiva, puede usar esta función: prueba estos datos:

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

aquí está la función:

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;   
}
$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
];
*/

Me gusta la solución de KernelM, pero necesitaba algo que pudiera manejar posibles conflictos clave (donde una nueva clave puede coincidir con una clave existente). Aquí está lo que se me ocurrió:

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

Luego puedes pasar por una matriz como esta:

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

Aquí hay una función de ayuda para lograrlo:

/**
 * 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;
    }
}

bastante basado en @KernelM answer .

Uso:

_rename_arr_key('oldkey', 'newkey', $my_array);

Devolverá true si se cambia correctamente, de lo contrario, false .

Cosas fáciles:

esta función aceptará el $ hash de destino y los reemplazos de $ también son un hash que contiene newkey = > asociaciones de teclas antiguas .

Esta función conservará el orden original , pero podría ser problemática para arrays muy grandes (como los registros de más de 10k) con respecto al rendimiento de & amp; memoria .

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

esta función alternativa haría lo mismo, con un rendimiento mucho mejor & amp; uso de la memoria, a costa de perder el pedido original (lo que no debería ser un problema, ya que es una tabla hash)

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

este código ayudará a cambiar la clave antigua a una nueva

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

mostrar como

$keys_array=array("one"=>"one","two"=>"two");

esto funciona para cambiar el nombre de la primera clave:

$a = ['catine' => 'cat', 'canine'  => 'dog'];
$tmpa['feline'] = $a['catine'];
unset($a['catine']);
$a = $tmpa + $a;

luego, print_r ($ a) representa una matriz reparada en orden:

Array
(
    [feline] => cat
    [canine] => dog
)

esto funciona para cambiar el nombre de una clave arbitraria:

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

una función generalizada:

function renameKey($oldkey, $newkey, $array) {
    $val = $array[$oldkey];
    $tmp_A = array_flip($array);
    $tmp_A[$val] = $newkey;

    return array_flip($tmp_A);
}

Si desea reemplazar varias claves a la vez (conservando el orden):

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

Uso:

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

Hay una forma alternativa de cambiar la clave de un elemento de matriz cuando se trabaja con una matriz completa, sin cambiar el orden de la matriz. Es simplemente copiar la matriz en una nueva matriz.

Por ejemplo, estaba trabajando con una matriz mixta y multidimensional que contenía claves indexadas y asociativas, y quería reemplazar las claves de enteros con sus valores, sin romper el orden.

Lo hice cambiando clave / valor para todas las entradas de la matriz numérica - aquí: ['0' = > 'foo']. Tenga en cuenta que el orden está intacto.

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

Salida:

Array (
    [foo] => 
    [bar] => alfa
    [baz] => Array (
            [a] => hello
            [b] => world
        )
)

Puedes usar esta función basada en 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));

Da:

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

Hmm, no he probado antes, pero creo que este código funciona

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

Uno que es fácil de entender para los conservadores:

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

la mejor manera es usar referencia y no usar unset (lo que da un paso más para limpiar la memoria)

$tab = ['two' => [] ];

solución:

$tab['newname'] = & $tab['two'];

tienes un original y una referencia con un nuevo nombre.

o si no quieres tener dos nombres en un valor, es bueno hacer otra pestaña y buscar en la referencia

foreach($tab as $key=> & $value) {
    if($key=='two') { 
        $newtab["newname"] = & $tab[$key];
     } else {
        $newtab[$key] = & $tab[$key];
     }
}

La iteración es mejor en las claves que en la clonación de todas las matrices y en la limpieza de las matrices antiguas si tiene datos largos como 100 filas +++ etc.

Puede escribir una función simple que aplica la devolución de llamada a las teclas de la matriz dada. Similar a 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}}

Aquí hay un resumen https://gist.github.com/vardius / 650367e15abfb58bcd72ca47eff096ca # file-array_map_keys-php .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top