Wie ändern Sie in PHP den Schlüssel eines Array-Elements?


348

Ich habe ein assoziatives Array in der Form, key => valuein der der Schlüssel ein numerischer Wert ist, jedoch kein sequentieller numerischer Wert. Der Schlüssel ist eigentlich eine ID-Nummer und der Wert ist eine Zählung. Dies ist für die meisten Fälle in Ordnung, ich möchte jedoch eine Funktion, die den für Menschen lesbaren Namen des Arrays abruft und diesen für den Schlüssel verwendet, ohne den Wert zu ändern.

Ich habe keine Funktion gesehen, die dies tut, aber ich gehe davon aus, dass ich den alten und den neuen Schlüssel (die ich beide habe) bereitstellen und das Array transformieren muss. Gibt es eine effiziente Möglichkeit, dies zu tun?


Antworten:


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

5
Seien Sie nur vorsichtig, dass 1) keine zwei Schlüssel die gleiche für Menschen lesbare Version haben 2) Keine für Menschen lesbaren Versionen zufällig Zahlen sind
Greg

81
Dies würde vermutlich auch die Reihenfolge des Arrays ändern, auf die Sie möglicherweise achten müssen. Sogar assoziative Arrays in PHP werden geordnet, und manchmal wird diese Reihenfolge genutzt.
Robin Winslow

7
Ja, großartiger Punkt, Robin. Gibt es eine Möglichkeit, die gleiche Reihenfolge beizubehalten? Oder müssen Sie ein neues Array erstellen, um dies zu erreichen?
Simon East

40
Bonusfrage: Wie ändere ich die ID, behalte aber die Array-Reihenfolge bei?
Petr Peller

17
Wenn sich der Schlüsselwert nicht ändert, löschen Sie ein Array-Element. Vielleicht möchten Sie es überprüfen.
Peeech

97

Sie würden dies tun und die Reihenfolge des Arrays beibehalten, indem Sie die Array-Schlüssel in ein separates Array einfügen, den Schlüssel in diesem Array suchen und ersetzen und ihn dann wieder mit den Werten kombinieren.

Hier ist eine Funktion, die genau das tut:

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

2
Vielen Dank, das war wirklich hilfreich, da ich die Reihenfolge des Arrays beibehalten musste. Ich hatte die akzeptierte Antwort bereits ausprobiert, bevor ich diese Seite fand.
Gillytech

3
Ja viel lieber die Reihenfolge des Arrays beibehalten, sieht ordentlicher aus.
Phil Cook

2
Musste die Schlüsselreihenfolge bewahren, gute, wirkte wie ein Zauber!
Lerner


54

Wenn Ihr arrayaus einer Datenbankabfrage erstellt wurde, können Sie den Schlüssel direkt aus der mysqlAnweisung heraus ändern :

anstatt

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

benutze so etwas wie:

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

tolle Antwort, sehr wertvoll!
DevMoutarde

20

Die Antwort von KernelM ist nett, aber um das von Greg im Kommentar angesprochene Problem (widersprüchliche Schlüssel) zu vermeiden, wäre die Verwendung eines neuen Arrays sicherer

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

Dies ist eine gute Lösung, solange Ihr Array eine angemessene Größe hat. Wenn Ihr Array mehr als die Hälfte des verfügbaren PHP-Speichers belegt, funktioniert dies nicht.
Kingjeffrey

12
@kingjeffrey, nicht wirklich. Array-Werte werden nicht dupliziert, solange sie "nur kopiert" werden, ohne geändert zu werden. Wenn beispielsweise ein Array 10'000 Elemente enthält und 40 MB Speicher belegt, verbraucht das Kopieren Speicher, der zum Speichern von 10'000 nur Verweisen auf bereits vorhandene Werte anstelle von Kopien von Werten benötigt wird. Wenn also 1 Array 40 MB verbraucht, wird seine Kopie verwendet verbraucht möglicherweise 0,5 MB (getestet).
binaryLV

17

Sie können ein zweites assoziatives Array verwenden, das den IDs von Menschen lesbare Namen zuordnet. Das würde auch eine Viele-zu-1-Beziehung ergeben. Dann machen Sie so etwas:

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

11

Wenn Sie möchten, dass auch die Position des neuen Array-Schlüssels mit der alten übereinstimmt, können Sie Folgendes tun:

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

7

Wenn Ihr Array rekursiv ist, können Sie folgende Funktion verwenden: Testen Sie diese Daten:

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

Hier ist die Funktion:

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

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

3
Ich liebe mich meine Array-Funktionen. Ich wollte dies als einen netten Einzeiler vorschlagen, um alle Schlüssel umzubenennen und die Array-Reihenfolge beizubehalten, aber ich werde stattdessen Ihren empfehlen.
Herbst Leonard

6

Ich mag die Lösung von KernelM, aber ich brauchte etwas, das potenzielle Schlüsselkonflikte behandelt (bei denen ein neuer Schlüssel möglicherweise mit einem vorhandenen Schlüssel übereinstimmt). Folgendes habe ich mir ausgedacht:

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

Sie können dann ein Array wie folgt durchlaufen:

$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

Hier ist eine Hilfsfunktion, um dies zu erreichen:

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

ziemlich basierend auf @ KernelM Antwort .

Verwendungszweck:

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

Bei erfolgreicher Umbenennung wird true zurückgegeben , andernfalls false .


Beachten Sie, dass dies die Reihenfolge des Arrays ändert (das Element des umbenannten Schlüssels befindet sich am Ende des Arrays und nicht an derselben Position im Array wie ursprünglich). Außerdem würde ich einen Funktionsnamen normalerweise nicht mit einem Unterstrich beginnen (der traditionell zur Bezeichnung spezieller Funktionen für den internen Gebrauch verwendet wird).
oder

4

Einfaches Zeug:

Diese Funktion akzeptiert den Ziel-Hash $ has und $ replace ist auch ein Hash, der newkey => oldkey-Assoziationen enthält .

Diese Funktion behält die ursprüngliche Reihenfolge bei , kann jedoch für sehr große Arrays (wie über 10.000 Datensätze) in Bezug auf Leistung und Speicher problematisch sein .

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

Diese alternative Funktion würde dasselbe tun, mit weitaus besserer Leistung und Speichernutzung, auf Kosten des Verlusts der ursprünglichen Bestellung (was kein Problem sein sollte, da es sich um eine Hashtabelle handelt!).

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

Dieser Code hilft dabei, den alten Schlüssel in einen neuen zu ändern

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

Anzeige wie

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

3

Einfacher Benchmark-Vergleich beider Lösungen.

Lösung 1 Kopieren und entfernen Sie (Bestellung verloren) https://stackoverflow.com/a/240676/1617857

for ($i =0; $i < 100000000; $i++){
    $array = ['test' => 'value'];
    $array['test2'] = $array['test'];
    unset($array['test']);
}

Lösung 2 Benennen Sie den Schlüssel https://stackoverflow.com/a/21299719/1617857 um

for ($i =0; $i < 100000000; $i++){
    $array = ['test' => 'value'];
    $keys = array_keys( $array );
    $keys[array_search('test', $keys, true)] = 'test2';
    array_combine( $keys, $array );
}

Ergebnisse:

php solution1.php  6.33s  user 0.02s system 99% cpu 6.356  total
php solution1.php  6.37s  user 0.01s system 99% cpu 6.390  total
php solution2.php  12.14s user 0.01s system 99% cpu 12.164 total
php solution2.php  12.57s user 0.03s system 99% cpu 12.612 total

2

Sie können diese Funktion basierend auf array_walk verwenden:

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

Es gibt:

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

1

Dies funktioniert zum Umbenennen des ersten Schlüssels:

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

dann rendert print_r ($ a) ein repariertes Array in der Reihenfolge:

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

Dies funktioniert zum Umbenennen eines beliebigen Schlüssels:

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

eine verallgemeinerte Funktion:

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

    return array_flip($tmp_A);
}

1

Wenn Sie mehrere Schlüssel gleichzeitig ersetzen möchten (Reihenfolge beibehalten):

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

Verwendungszweck:

$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

Es gibt eine alternative Möglichkeit, den Schlüssel eines Array-Elements zu ändern, wenn Sie mit einem vollständigen Array arbeiten - ohne die Reihenfolge des Arrays zu ändern. Es ist einfach, das Array in ein neues Array zu kopieren.

Ich habe zum Beispiel mit einem gemischten, mehrdimensionalen Array gearbeitet, das indizierte und assoziative Schlüssel enthielt - und ich wollte die ganzzahligen Schlüssel durch ihre Werte ersetzen, ohne die Reihenfolge zu unterbrechen.

Ich habe dazu Schlüssel / Wert für alle numerischen Array-Einträge gewechselt - hier: ['0' => 'foo']. Beachten Sie, dass die Bestellung intakt ist.

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

Ausgabe:

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

1

Der beste Weg ist die Verwendung von Referenz und nicht die Verwendung von Unset (was einen weiteren Schritt zum Bereinigen des Speichers darstellt).

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

Lösung:

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

Sie haben ein Original und eine Referenz mit neuem Namen.

oder wenn Sie nicht möchten, dass zwei Namen in einem Wert enthalten sind, erstellen Sie eine andere Registerkarte und suchen Sie nach einer Referenz

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

Die Iterration ist bei Schlüsseln besser als das Klonen aller Arrays und das Bereinigen alter Arrays, wenn Sie lange Daten wie 100 Zeilen +++ usw. haben.


0

Hmm, ich bin noch kein Test, aber ich denke, dieser Code funktioniert

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

Json kodieren und dekodieren? Das ist eine wirklich schlechte Antwort.
Kixorz

0

Eine, deren Bestellung einfach zu verstehen ist:

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

Sie können eine einfache Funktion schreiben, die den Rückruf auf die Schlüssel des angegebenen Arrays anwendet. Ähnlich wie 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}}

Hier ist eine Übersicht https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php .


0

Diese Funktion benennt einen Array-Schlüssel unter Beibehaltung seiner Position um, indem er ihn mit der Indexsuche kombiniert.

function renameArrKey($arr, $oldKey, $newKey){
    if(!isset($arr[$oldKey])) return $arr; // Failsafe
    $keys = array_keys($arr);
    $keys[array_search($oldKey, $keys)] = $newKey;
    $newArr = array_combine($keys, $arr);
    return $newArr;
}

Verwendungszweck:

$arr = renameArrKey($arr, 'old_key', 'new_key');

-1

Diese Grundfunktion behandelt das Austauschen von Array-Schlüsseln und das Halten des Arrays in der ursprünglichen Reihenfolge ...

public function keySwap(array $resource, array $keys)
{
    $newResource = [];

    foreach($resource as $k => $r){
        if(array_key_exists($k,$keys)){
            $newResource[$keys[$k]] = $r;
        }else{
            $newResource[$k] = $r;
        }
    }

    return $newResource;
}

Sie könnten dann alle 'a'-Tasten durchlaufen und zum Beispiel mit' z 'tauschen ...

$inputs = [
  0 => ['a'=>'1','b'=>'2'],
  1 => ['a'=>'3','b'=>'4']
]

$keySwap = ['a'=>'z'];

foreach($inputs as $k=>$i){
    $inputs[$k] = $this->keySwap($i,$keySwap);
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.