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?

Thomas Owens
quelle
Siehe ähnliche stackoverflow.com/q/308703
Peter Krauss

Antworten:

576
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
KernelM
quelle
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 );
}
DiverseAndRemote.com
quelle
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
Denken
Léo Benoist
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´..."
Simon Franco
quelle
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);
kjg
quelle
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']];
Tom Ritter
quelle
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;
}
verbreitenzz
quelle
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;   
}
pajafumo
quelle
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
];
*/
Temuri
quelle
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' )
Kingjeffrey
quelle
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 .

Kenorb
quelle
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;       
}
Nadir
quelle
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");
karthikeyan ganesan
quelle
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
Léo Benoist
quelle
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
    )
)
Alekzander
quelle
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);
}
wmmso
quelle
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);
Lepe
quelle
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
        )
)
Kristoffer Bohmann
quelle
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.

Kamil Dąbrowski
quelle
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);
}
Frank Vu
quelle
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;
}
Andrew
quelle
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 .

vardius
quelle
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');
Gewähren
quelle
-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);
}
MikeyJ
quelle