Как заставить 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;
}
A var_dump()
все еще показывает их как целые индексы массива.
Есть ли способ заставить клавиши быть строками, поэтому я могу изменить порядок их, не разрушая массив?
Ответы
Ответ 1
ИЗМЕНИТЬ
Я предположил, что если они целые, я не могут изменять их без изменения ключ (что важно в этом пример). Однако, если бы они были строки, я могу переупорядочить их, как они как индекс не должен быть интерпретируются как имеющие имея в виду. В любом случае, см. Мой вопрос обновить, как я это сделал (я спустился другой маршрут).
На самом деле они не должны быть в числовом порядке...
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
Ответ 2
как насчет этого?
$newArray = array();
foreach($oldArray as $key => $value) {
$newArray[$key.''] = $value;
}
изменить:
тоже пробовал и да, это не сработало.
Из Документы PHP:
Ключ может быть либо целым, либо строка. Если ключ является стандартным представление целого числа, это будет интерпретироваться как таковое (т.е. "8" интерпретироваться как 8, а "08" - интерпретироваться как "08" ). Поплавки в ключе усекаются до целого. Нет различные индексированные и ассоциативные типы массивов в PHP; здесь только один тип массива, который может содержать целочисленные и строковые индексы.
Я думаю, теперь это зависит от того, как вы хотите отсортировать массив. (окончательный выход?)
Ответ 3
Используйте объект вместо массива $object = (object)$array;
Ответ 4
Мне удалось заставить это работать, добавив '.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)
Он может быть не совсем оптимальным, но он позволяет вам сортировать массив и извлекать (эквивалент) исходный ключ без необходимости урезать что-либо.
Ответ 5
ВЫ НЕ МОЖЕТЕ!
Строки, содержащие действительные целые числа, будут переданы в целочисленный тип. Например. ключ "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.
Вот несколько успешных попыток создания массива со значениями строки типа.
$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"
Изменить:
НАСТОЯЩИМ ВЫ МОЖЕТЕ!
Передача последовательного массива в ассоциативный массив
Все, что ни за что
Ответ 6
Вы можете добавить нулевой символ "\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"
результирующий массив будет:
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()
покажет вам там нулевой символ в конце, не знаю, почему вы получаете "Undefined offset". Поэтому используйте этот хак, если итерация через foreach()
или тот, кто закончит поддерживать ваш код, будет вас ненавидеть.
Ответ 7
Изменить:
Это должно работать
foreach($array as $key => $value) {
$newkey = sprintf('%s',$key);
$newArray["'$newkey'"] = $value;
}