web-dev-qa-db-fra.com

En PHP, comment changez-vous la clé d'un élément de tableau?

J'ai un tableau associatif sous la forme key => value où clé est une valeur numérique, mais ce n'est pas une valeur numérique séquentielle. La clé est en fait un numéro d'identification et la valeur est un compte. Cela convient dans la plupart des cas, mais je souhaite une fonction qui obtienne le nom du tableau lisible par l’homme et l’utilise pour la clé, sans modifier la valeur.

Je n'ai pas vu de fonction qui fait cela, mais je suppose que je dois fournir l'ancienne clé et la nouvelle clé (que j'ai toutes les deux) et transformer le tableau. Y a-t-il un moyen efficace de le faire?

315
Thomas Owens
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
495
KernelM

Pour ce faire, tout en préservant l'ordre du tableau, vous devez placer les clés du tableau dans un tableau séparé, rechercher et remplacer la clé de ce tableau, puis la combiner avec les valeurs. 

Voici une fonction qui fait exactement cela:

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

si votre array est construite à partir d'une requête de base de données, vous pouvez modifier la clé directement à partir de l'instruction mysql:

au lieu de

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

utiliser quelque chose comme:

"select ´id´ **as NEWNAME** from ´tablename´..."
46
Simon Franco

La réponse de KernelM est Nice, mais pour éviter le problème soulevé par Greg dans le commentaire (clés en conflit), l’utilisation d’un nouveau tableau serait plus sûre.

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

Vous pouvez utiliser un second tableau associatif qui mappe les noms lisibles par l'homme aux identifiants. Cela fournirait également une relation plusieurs à un. Alors fais quelque chose comme ça:

echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];
15
Tom Ritter

Si vous souhaitez également que la position de la nouvelle clé de tableau soit la même que l'ancienne, procédez comme suit:

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

Voici une fonction d'assistance pour y parvenir:

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

plutôt basé sur @KernelM answer .

Usage:

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

Il renverra true en cas de renommage réussi, sinon false.

6
kenorb

Si votre tableau est récursif, vous pouvez utiliser cette fonction: Tester ces données:

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

voici la fonction:

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

J'aime la solution de KernelM, mais j'avais besoin de quelque chose qui gèrerait des conflits de clés potentiels (lorsqu'une nouvelle clé peut correspondre à une clé existante). Voici ce que je suis venu avec:

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

Vous pouvez ensuite parcourir un tableau comme celui-ci:

$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' )
6
kingjeffrey
$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
];
*/
6
temuri

Truc facile:

cette fonction acceptera la cible $ hash et $ remplacements sera aussi un hash contenant newkey => oldkey associations .

Cette fonction conservera l'ordre d'origine , mais pourrait poser problème pour les baies très volumineuses (comme ci-dessus 10 000 enregistrements) concernant performance & memory .

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

cette fonction alternative ferait de même, avec des performances bien meilleures & une utilisation de la mémoire, au prix de la perte de la commande d'origine (ce qui ne devrait pas poser de problème puisqu'il s'agit d'une table de hachage!)

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

ce code aidera à changer l'ancien clé en un nouveau

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

afficher comme

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

Il existe un autre moyen de changer la clé d'un élément de tableau lorsque vous travaillez avec un tableau complet - sans modifier l'ordre du tableau . Il s'agit simplement de copier le tableau dans un nouveau tableau.

Par exemple, je travaillais avec un tableau mixte multidimensionnel contenant des clés indexées et associatives - et je voulais remplacer les clés entières par leurs valeurs, sans rompre l'ordre.

Je l’ai fait en changeant la clé/la valeur de toutes les entrées numériques du tableau - ici: ['0' => 'foo']. Notez que la commande est intacte.

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

Sortie:

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

cela fonctionne pour renommer la première clé:

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

alors, print_r ($ a) restitue un tableau dans l’ordre réparé:

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

cela fonctionne pour renommer une clé arbitraire:

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

une fonction généralisée:

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

    return array_flip($tmp_A);
}
1
wmmso

Si vous souhaitez remplacer plusieurs clés à la fois (en préservant l'ordre):

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

Usage:

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

Hmm, je ne suis pas testé avant, mais je pense que ce code fonctionne

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);
}
0
Frank Vu

le meilleur moyen est d’utiliser référence, et non d’utiliser unset (ce qui constitue une étape supplémentaire pour nettoyer la mémoire)

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

solution:

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

vous avez un original et une référence avec un nouveau nom.

ou si vous ne voulez pas avoir deux noms dans une valeur est bon faites un autre onglet et foreach sur la référence

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

L’itération est meilleure pour les clés que pour le clonage de tous les tableaux, et le nettoyage de l’ancien tableau si vous avez des données longues comme 100 rangées +++ etc.

0
Kamil Dąbrowski

Vous pouvez écrire une fonction simple qui applique le rappel aux clés du tableau donné. Similaire à 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}}

Voici un Gist https://Gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php .

0
vardius

Vous pouvez utiliser cette fonction basée sur 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));

Il donne:

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

Celui qui préserve la commande est simple à comprendre:

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