Я столкнулся с старым приложением, которое использует идентификатор для имен массива типов, например …
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; }