Как заставить PHP использовать строки для ключей массива?

Я столкнулся с старым приложением, которое использует идентификатор для имен массива типов, например …

array(1) { [280]=> string(3) "abc" } 

Теперь мне нужно переупорядочить их, и var_dump() заставит себя казаться, что это не произойдет, когда ключи целые.

Если я добавлю a к каждому индексу, var_dump() покажет двойные кавычки вокруг ключа, я думаю, что теперь это строка …

 array(1) { ["280a"]=> string(3) "abc" } 

Это позволит мне легко переупорядочить их, не касаясь большего количества кода.

Это не работает .

 $newArray = array(); foreach($array as $key => $value) { $newArray[(string) $key] = $value; } 

var_dump() все еще показывает их как целые индексы массива.

Есть ли способ заставить клавиши быть строками, поэтому я могу их переупорядочить, не разрушая массив?

EDIT :

Я предположил, что если они являются целыми числами, я не могу их переупорядочить без изменения ключа (что важно в этом примере). Однако, если они были строками, я могу переупорядочить их, как им нравится, поскольку индекс не должен интерпретироваться, чтобы иметь какое-либо особое значение. В любом случае, см. Мое обновление вопроса о том, как я это сделал (я пошел по другому пути).

На самом деле они не должны быть в числовом порядке …

 array(208=>'a', 0=> 'b', 99=>'c'); 

Совершенно верно, если вы назначили их вручную. Хотя я согласен, что целые ключи могут быть неверно истолкованы как имеющие последовательный смысл кем-то, хотя вы бы подумали, что если бы они были в нечисловом порядке, было бы очевидно, что они не были уверены. Это говорит, что я думаю, так как у вас есть свобода, чтобы изменить код по мере обновления, это лучший подход.


Вероятно, это не самый эффективный способ, но легкий, как пирог:

 $keys = array_keys($data); $values = array_values($data); $stringKeys = array_map('strval', $keys); $data = array_combine($stringKeys, $values); //sort your data 

как насчет этого?

 $newArray = array(); foreach($oldArray as $key => $value) { $newArray[$key.''] = $value; } 

edit: попробовал тоже и да, это не сработало.

Из документов PHP :

Ключ может быть целым числом или строкой. Если ключ является стандартным представлением целого числа, он будет интерпретироваться как таковой (т.е. «8» будет интерпретирован как 8, а «08» будет интерпретирован как «08»). Поплавки в ключе усекаются до целого. В PHP нет разных индексированных и ассоциативных типов массивов; существует только один тип массива, который может содержать как целые, так и строковые индексы.

Думаю, теперь это зависит от того, как вы хотите отсортировать массив. (конечный результат?)

Используйте объект вместо массива $object = (object)$array;

Я смог заставить это работать, добавив «.0» в конец каждого ключа, как таковой:

 $options = []; for ($i = 1; $i <= 4; $i++) { $options[$i.'.0'] = $i; } 

Вернется:

array("1.0" => 1, "2.0" => 2, "3.0" => 3, "4.0" => 4)

Он может быть не совсем оптимальным, но он позволяет вам сортировать массив и извлекать (эквивалент) исходный ключ без необходимости урезать что-либо.

ВЫ НЕ МОЖЕТЕ!

Строки, содержащие действительные целые числа, будут переданы в целочисленный тип. Например, ключ «8» будет фактически сохранен под 8. С другой стороны, «08» не будет выбрано, так как это не допустимое целое число.

Редактировать:

В самом деле, вы можете! Внедрить последовательный массив в ассоциативный массив

 $obj = new stdClass; foreach($array as $key => $value){ $obj->{$key} = $value; } $array = (array) $obj; 

В большинстве случаев это верно.

Строки, содержащие действительные целые числа, будут переданы в целочисленный тип. Например, ключ «8» будет фактически сохранен под 8. С другой стороны, «08» не будет выбрано, так как это не допустимое целое число.

Эти примеры из PHP-документов

  <?php $array = array( 1 => "a", "1" => "b", 1.5 => "c", true => "d", ); var_dump($array); ?> 

Вышеприведенный пример выводит:

 array(1) { [1]=> string(1) "d" } 

Поэтому, даже если вы должны были создать массив с пронумерованными клавишами, они просто будут возвращены в целые числа.

К сожалению, для меня я не знал об этом до недавнего времени, но, хотя я бы поделился своими неудачными попытками.

Неудачные попытки

 $arr = array_​change_​key_​case($arr); // worth a try. 

Возвращает массив со всеми ключами из массива с нижним или верхним регистром. Нумерованные индексы остаются как есть .

Мои последующие попытки состояли в создании нового массива array_combine при старых значениях новых (строковых) ключей.

Я попробовал несколько способов сделать массив $keys содержащим числовые значения строки типа.

range("A", "Z" ) работает для алфавита, поэтому, хотя я бы попробовал его с числовой строкой.

 $keys = range("0", (string) count($arr) ); // integers 

Это привело к массиву с ключами, но все они были типа int.

Вот несколько успешных попыток создания массива со значениями типа string.

 $keys = explode(',', implode(",", array_keys($arr))); // values strings $keys = array_map('strval', array_keys($arr)); // values strings 

Теперь просто чтобы объединить два.

 $arr = array_combine( $keys, $arr); 

Это когда я обнаружил, что числовые строки отлиты от целых чисел.

 $arr = array_combine( $keys, $arr); // int strings //assert($arr === array_values($arr)) // true. 

Единственный способ изменить ключи на строки и сохранить их литеральные значения – это префикс ключа с суффиксом с десятичной точкой "00","01","02" или "0.","1.","2." ,

Вы можете добиться этого так.

 $keys = explode(',', implode(".,", array_keys($arr)) . '.'); // added decimal point $arr = array_combine($keys, $arr); 

Конечно, это не так идеально, как вам нужно будет таргетировать элементы массива, подобные этому.

 $arr["280."] 

Я создал небольшую функцию, которая будет нацелена на правильный элемент массива, даже если вы вводите только целое число, а не новую строку.

 function array_value($array, $key){ if(array_key_exists($key, $array)){ return $array[ $key ]; } if(is_numeric($key) && array_key_exists('.' . $key, $array)){ return $array[ '.' . $key ]; } return null; } 

Применение

 echo array_value($array, "208"); // "abc" 

Редактировать:

В самом деле, вы можете! Внедрить последовательный массив в ассоциативный массив

Все это ни для чего

Вы можете добавить нулевой символ "\0" в конец ключа массива. Это делает так, что PHP не может интерпретировать строку как целое. На нем работают все функции массива (например, array_merge() ). Также даже var_dump() не покажет ничего лишнего после строки целых чисел.

Пример:

 $numbers1 = array(); $numbers2 = array(); $numbers = array(); $pool1 = array(111, 222, 333, 444); $pool2 = array(555, 666, 777, 888); foreach($pool1 as $p1) { $numbers1[$p1 . "\0"] = $p1; } foreach($pool2 as $p2) { $numbers2[$p2 . "\0"] = $p2; } $numbers = array_merge($numbers1, $numbers2); var_dump($numbers); 

Результирующий результат будет:

 array(8) { ["111"] => string(3) "111" ["222"] => string(3) "222" ["333"] => string(3) "333" ["444"] => string(3) "444" ["555"] => string(3) "555" ["666"] => string(3) "666" ["777"] => string(3) "777" ["888"] => string(3) "888" } 

Без . "\0" . "\0" часть результирующего массива будет:

 array(8) { [0] => string(3) "111" [1] => string(3) "222" [2] => string(3) "333" [3] => string(3) "444" [4] => string(3) "555" [5] => string(3) "666" [6] => string(3) "777" [7] => string(3) "888" } 

Также ksort() также игнорирует нулевой символ, означающий $numbers[111] а $numbers["111\0"] будут иметь одинаковый вес в алгоритме сортировки.

Единственным недостатком этого метода является то, что для доступа, например $numbers["444"] , вам действительно нужно будет получить к нему доступ через $numbers["444\0"] и поскольку даже var_dump() покажет вам, что есть нулевой символ в конце, нет никакой подсказки относительно того, почему вы получаете «Неопределенное смещение». Поэтому используйте этот хак, если итерация через foreach() или тот, кто закончит поддерживать ваш код, будет вас ненавидеть.

Изменить: это должно работать

 foreach($array as $key => $value) { $newkey = sprintf('%s',$key); $newArray["'$newkey'"] = $value; }