2012-01-16 2 views
18

Вы можете "change" the key of an array element просто установив новый ключ и удаление старого:Изменить ключ массива без изменения порядка

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

Но это будет переместить ключ к концу массива.

Есть ли элегантный способ изменения ключа без изменения порядка?

(PS:. Этот вопрос просто из концептуального интереса, а не потому, что мне это нужно где-нибудь)

+0

Я бы предположил, что какая-то уродливая конструкция с array_splice() и array_slice() будет делать трюк –

+0

@MarcB Это не работает со строковыми клавишами. – NikiC

+0

Я не программист на PHP, но что в мире есть семантика '$ arr [$ oldKey]', если это работает как аргумент функции, которая удаляет '$ oldKey' из' $ arr'? Я думаю, что PHP может быть более интересным, чем я думал раньше, придется заглянуть в это ... –

ответ

25

протестирована и работает :)

$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 Хотя вы, вероятно, должны добавить обработчик ошибок для случая, когда '$ old_key' не находится в массиве. –

+0

Только если ключ не существует, замените его первым. Добавьте предложение if, и youre ok;) – Kristian

+0

Не лучше ли было бы вернуть неизменный массив вместо того, чтобы бросать исключение? –

-1

Сделайте двойной щелчок! По крайней мере, все, что я могу думать:

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

И это просто теория, я не проверял, работает ли она, но я думаю, что это будет. –

+5

Это не удастся, если есть повторяющиеся значения. –

+0

Истинный .... привет, тогда у меня нет идей. –

6

Одним из способов было бы просто использовать Еогеасп Перебор массива и скопировать его в новый массив, изменения ключа условно в то время как итерация, например, если $ ключевых === «Foo», то не использовать Foo, но бар:

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

Другой способ снова стать serialize массива str_replace сериализованные ключа, а затем unserialize обратно в массив. Это не особенно элегантная, хотя и вероятная склонность к ошибкам, особенно если у вас нет только скаляров или многомерных массивов.

Третий путь - мой любимый - бы вы писать array_key_rename в C и предлагать его для ядра PHP;)

+0

Доступен ли $ newArray из-за пределов foreach? – nawfal

+0

@nawfal да, но не вне функции, если вы не назначили возвращаемое значение – Gordon

+0

OK. Немного странно, чтобы привыкнуть к PHP, поступающему с другого языка :) – nawfal

-2

Вы можете использовать array_combine. Он объединяет массив для ключей, а другой для значений ...

Например:

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

Что делать, если у вас много ключей и вы хотите изменить один? С вашим решением вы должны были бы написать бесконечный массив $ new_keys. –

9

Нечто подобное может также работать:

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

ВЫВОД:

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

Я лично считаю это решение очень элегантным! +1 –

+3

Я тоже. Это отлично работает для удаления тире/подчеркивания из имен тегов XML при использовании Zend_Config_XML :: toArray(). В моем случае данные являются параметрами для отдельных элементов w/optgroups. Мои имена optgroup были тегами XML, а заголовки имели тире. Это хорошо сработало для этого. – axiom82

+3

Я не нахожу этот элегантный. Очень опасно. – nawfal

0

Мы используем эту функцию для изменения нескольких ключей массива в пределах rray поддержанию порядка:

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

Вы можете передать массив в $ keys_map, как это:

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

Это решение основано на Kristian один.

Смежные вопросы