в php, как вы меняете ключ элемента массива?

<p>у меня есть ассоциативный массив в виде <code>key => value</code>, где ключ является числовым значением, однако это не последовательное числовое значение. ключ на самом деле является идентификационным номером, а значение - счетчиком. это хорошо для большинства случаев, однако я хочу функцию, которая получает удобочитаемое имя массива и использует его для ключа без изменения значения.</p><p>я не видел функцию, которая делает это, но я предполагаю, что мне нужно предоставить старый ключ и новый ключ (оба из которых у меня есть) и преобразовать массив. есть ли эффективный способ сделать это?</p>

<pre><code>$arr[$newkey] = $arr[$oldkey]; unset($arr[$oldkey]); </code></pre>

<p>чтобы сделать это и сохранить порядок массива, нужно поместить ключи массива в отдельный массив, найти и заменить ключ в этом массиве, а затем объединить его со значениями. </p><p>вот функция, которая делает именно это:</p><pre><code>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 ); } </code></pre>

<p>если ваш <code>array</code> построен из запроса к базе данных, вы можете изменить ключ непосредственно из оператора <code>mysql</code>:</p><p>вместо</p><pre><code>"select ´id´ from ´tablename´..." </code></pre><p>использовать что-то вроде:</p><pre><code>"select ´id´ **as newname** from ´tablename´..." </code></pre>

<p>ответ от kernelm - хороший, но во избежание проблемы, поднятой грегом в комментарии (конфликтующие ключи), было бы безопаснее использовать новый массив</p><pre><code>$newarr[$newkey] = $oldarr[$oldkey]; $oldarr=$newarr; unset($newarr); 

вы можете использовать второй ассоциативный массив, который отображает понятные человеку имена на идентификаторы. это также обеспечило бы отношение «многие к 1». затем сделайте что-то вроде этого:<blockquote> echo 'widgets: ' . $data[$humanreadblemapping['widgets']];  </blockquote>

если вы хотите, чтобы позиция нового ключа массива была такой же, как и у старого, вы можете сделать это: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; } </code></pre>

<p>вот вспомогательная функция для достижения этой цели:</p><pre><code>/** * 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; } } довольно основанный на <a href="https://stackoverflow.com/a/240676/55075">@kernelm ответ .использование:_rename_arr_key('oldkey', 'newkey', $my\_array); </code></pre><p>он вернет <em>true</em> при успешном переименовании, иначе <em>false</em>.</p>

<p>если ваш массив рекурсивный, вы можете использовать эту функцию: test this data:</p><pre><code> $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, ) ); вот функция: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; } </code></pre>

<p>мне нравится решение kernelm, но мне нужно что-то, что могло бы справиться с потенциальными конфликтами ключей (где новый ключ может соответствовать существующему ключу). вот что я придумал:</p><pre><code>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; } } </code></pre><p>затем вы можете циклически перебирать массив следующим образом:</p><pre><code>$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' ) </code></pre>

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

<p>легкие вещи:</p><p>эта функция будет принимать целевой $ hash, а $ replacements также является хешем, содержащим<strong> newkey => ассоциации старых ключей </strong>.</p><p>эта функция<strong> сохранит исходный порядок </strong>, но может быть проблематичной для очень больших (например, более 10 тыс. записей) массивов, касающихся<strong> производительности и памяти </strong>.</p><pre><code>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; } эта альтернативная функция будет делать то же самое, с<strong> гораздо лучшей производительностью </strong>& использованием памяти, за счет потери исходного порядка (что не должно быть проблемой, так как она хеш-таблица!)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; } 

этот код поможет заменить старый ключ на новый$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); показывать как$keys\_array=array("one"=>"one","two"=>"two"); </code></pre>

<p>есть альтернативный способ изменить ключ элемента массива при работе с полным массивом - без изменения порядка массива .... это просто скопировать массив в новый массив.</p><p>например, я работал со смешанным многомерным массивом, который содержал индексированные и ассоциативные ключи - и я хотел заменить целочисленные ключи их значениями, не нарушая порядок.</p><p>я сделал это, переключив ключ/значение для всех записей числового массива - здесь: ['0' => 'foo']. обратите внимание, что заказ не поврежден.</p><pre><code><?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); результат:array ( [foo] => [bar] => alfa [baz] => array ( [a] => hello [b] => world ) ) 

это работает для переименования первого ключа:$a = ['catine' => 'cat', 'canine' => 'dog']; $tmpa['feline'] = $a['catine']; unset($a['catine']); $a = $tmpa + $a; </code></pre><p>затем print\_r ($ a) отображает восстановленный массив в порядке:array ( [feline] => cat [canine] => dog ) это работает для переименования произвольного ключа:$a = ['canine' => 'dog', 'catine' => 'cat', 'porcine' => 'pig'] $af = array_flip($a) $af['cat'] = 'feline'; $a = array\_flip($af) print_r ($ а)</p><pre><code>array ( [canine] => dog [feline] => cat [porcine] => pig ) </code></pre><p>обобщенная функция:</p><pre><code>function renamekey($oldkey, $newkey, $array) { $val = $array[$oldkey]; $tmp_a = array_flip($array); $tmp_a[$val] = $newkey; return array_flip($tmp\_a); } </code></pre>

<p>если вы хотите заменить несколько ключей одновременно (сохраняя порядок):</p><pre><code>/** * 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)); } </code></pre><p>использование:</p><pre><code>$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); </code></pre>

<p>хм, я не тестировал раньше, но я думаю, что этот код работает</p><pre><code>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); } </code></pre>

<p>лучший способ - использовать ссылку, а не использовать unset (что делает еще один шаг для очистки памяти)</p><pre><code>$tab = ['two' => [] ]; решение:$tab['newname'] = & $tab['two']; у вас есть один оригинал и одна ссылка с новым именем.или, если вы не хотите иметь два имени в одном значении, хорошо сделать другую вкладку и foreach по ссылкеforeach($tab as $key=> & $value) { if($key=='two') { $newtab["newname"] = & $tab[$key]; } else { $newtab[$key] = & $tab[$key]; } } </code></pre><p>итерация лучше для ключей, чем клонирование всего массива, и очистка старого массива, если у вас длинные данные, такие как 100 строк +++ и т.д.</p>

<p>вы можете использовать эту функцию на основе array\_walk:</p><pre><code>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)); </code></pre><p>это дает:</p><pre><code>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 ) ) </code></pre>

<p>тот, который сохраняет порядок, который прост для понимания:</p><pre><code>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; } </code></pre>