2010-11-04 3 views
80

Возможно ли использовать цифровую строку, такую ​​как "123", как ключ в массиве PHP, без преобразования в целое число?Числовая строка в виде массива в PHP

$blah = array('123' => 1); 
var_dump($blah); 

печатает

array(1) { 
    [123]=> 
    int(1) 
} 

Я хочу

array(1) { 
    ["123"]=> 
    int(1) 
} 
+7

Поскольку PHP свободно набирается, '' 123 '' == '123' практически для всех целей. Какая причина, по которой вы хотите, чтобы она была конкретно как строка (и наличие int было плохой)? – ircmaxell

+8

Причина, которая приходит мне на ум, относится к функциям массива типа 'array_merge' *. Если входные массивы имеют одинаковые строковые ключи, то более позднее значение для этого ключа перезапишет предыдущий. Если, однако, массивы содержат числовые keys **, более позднее значение не будет перезаписывать исходное значение, но будет добавлено. "* – ficuscr

+6

Другой пример, где числовые строки в виде ключей массива проблематичны: [' asort'] (http://php.net/manual/en /function.asort.php) – swenedo

ответ

68

Нет; нет, это не так:

От the manual:

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

Добавление

Из-за комментарии ниже, я подумал, что было бы интересно отметить, что поведение аналогично но не идентичны ключам объектов JavaScript.

foo = { '10' : 'bar' }; 

foo['10']; // "bar" 
foo[10]; // "bar" 
foo[012]; // "bar" 
foo['012']; // undefined! 
+22

... * shudders * ... – jameshfisher

+69

PHP, серверный IE. –

+5

Похоже, есть способ, на самом деле! Вы не согласны с этим ответом? http://stackoverflow.com/a/35180513/247696 – Flimm

5

Вы можете типаж ключ к строке, но в конечном итоге будет преобразовано в целое из-за рыхлой типизации PHP. Смотрите сами:

$x=array((string)123=>'abc'); 
var_dump($x); 
$x[123]='def'; 
var_dump($x); 

Из PHP инструкции:

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

+1

Преобразование происходит не из-за отсутствия набора текста; php определяет, будет ли строка * выглядеть * числовой, а затем преобразует ее. –

+0

Так ты говоришь, что это невозможно? [Этот ответ] (http://stackoverflow.com/a/35180513/247696) показывает, что есть способ использовать строку, которая выглядит как целое число как ключ в массиве. – Flimm

+0

IMHO Проблема заключается в интерпретаторе PHP. Невозможно даже представить себе язык, который смешивает строки и целые числа в виде ключей массива. Лучшее решение? Как было предложено Undolog http://stackoverflow.com/a/15413637/1977778, лучшим решением является использование конечного пространства ... К сожалению. – sentenza

12

Если вам нужно использовать числовой ключ в структуре данных php, объект будет работать. И объекты сохраняют порядок, поэтому вы можете выполнять итерацию.

$obj = new stdClass(); 
$key = '3'; 
$obj->$key = 'abc'; 
+0

Это очень хорошее предложение. Я пишу код рамки и сталкиваюсь с кем-то, передающим массив, который может иметь либо «случайную» индексацию: array («this», «that») или «ассоциативная» индексация: array (123 => array ('this', 'that «)). Теперь, благодаря вам, я могу просто набрать x;) +1 –

+0

Но можно ли использовать цифровую строку типа «123» в качестве ключа в массиве PHP без преобразования в целое число? – Flimm

+0

@ Flimm нет, что невозможно, поэтому я предлагаю свое решение. – steampowered

0

Я столкнулся с этой проблемой на массиве с кнопками «0» и «». Это означало, что я не мог проверить ключи массива с помощью == или ===.

$array=array(''=>'empty', '0'=>'zero', '1'=>'one'); 
echo "Test 1\n"; 
foreach ($array as $key=>$value) { 
    if ($key == '') { // Error - wrongly finds '0' as well 
     echo "$value\n"; 
    } 
} 
echo "Test 2\n"; 
foreach ($array as $key=>$value) { 
    if ($key === '0') { // Error - doesn't find '0' 
     echo "$value\n"; 
    } 
} 

Обходной путь - передать ключи массива обратно в строки перед использованием.

echo "Test 3\n"; 
foreach ($array as $key=>$value) { 
    if ((string)$key == '') { // Cast back to string - fixes problem 
     echo "$value\n"; 
    } 
} 
echo "Test 4\n"; 
foreach ($array as $key=>$value) { 
    if ((string)$key === '0') { // Cast back to string - fixes problem 
     echo "$value\n"; 
    } 
} 
+1

На самом деле это не ответ на вопрос. – Flimm

8

Мой обходной путь является:

$id = 55; 
$array = array(
    " $id" => $value 
); 

Пространство голец (перед именем) является хорошим решением, потому что держать Int преобразования:

foreach($array as $key => $value) { 
    echo $key; 
} 

Вы увидите 55 как междунар.

+3

Или '' 0 $ id "=> $ value'. Также работает Prepending с '0'. – nawfal

+0

@nawfal Спасибо, я не ожидал найти ответ здесь – Va1iant

+0

Итак, вы говорите, что невозможно использовать цифровую строку типа «123» в качестве ключа в массиве PHP без преобразования в целое число? – Flimm

0

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

Когда я использовал $data = array_merge($data, $extra); PHP будет «переупорядочивать» ключи. В попытке сделать заказ целые ключи (я пробовал с 6 - '6' - "6" даже (string)"6" в качестве ключей) получил переименование от 0 до n ... Если вы думаете об этом, то в большинстве случаев это было бы желательным поведением.

Вы можете обойти это, используя вместо этого $data = $data + $extra;. Довольно прямо вперед, но я не думал об этом сначала ^^.

+0

Точно такая же проблема привела меня к этой странице, но я должен сказать, что это не ответ на вопрос ОП. – Flimm

+0

@Flimm True. Но поиск ответа привел меня на эту страницу. Я решил, что мое решение может помочь другим гуглерам :) – Brainfeeder

-1

У меня была эта проблема при попытке отсортировать массив, в котором мне нужен ключ сортировки, чтобы он был шестнадцатеричным sha1. Когда полученное значение sha1 не имеет букв, PHP превращает ключ в целое. Но мне нужно было отсортировать массив по относительному порядку строк. Поэтому мне нужно было найти способ заставить ключ быть строкой, не меняя порядок сортировки.

Глядя на диаграмму ASCII (https://en.wikipedia.org/wiki/ASCII), восклицательный знак сортируется примерно так же, как и пространство, и, конечно, ниже всех цифр и букв.

Таким образом, я добавил восклицательный знак в конце ключевой строки.

for(...) { 

    $database[$sha.'!'] = array($sha,$name,$age); 
} 

ksort($database); 
$row = reset($database); 
$topsha = $row[0]; 
+0

Итак, вы говорите, что невозможно использовать цифровую строку типа «123» в качестве ключа в массиве PHP без преобразования в целое число? – Flimm

+0

Нет - он обрабатывает ключ, который является всеми числами как целое число при сортировке массива с помощью ksort() - он никогда не преобразуется в целое число - просто сравнивается как один во время сортировки. – drchuck

25

Да, можно с помощью массива интернатных stdClass объекта:

$data = new stdClass; 
$data->{"12"} = 37; 
$data = (array) $data; 
var_dump($data); 

Это дает вам (до PHP версии 7.1):

array(1) { 
    ["12"]=> 
    int(37) 
} 

(Update: Мой оригинала ответ показал более сложный способ, используя json_decode() и json_encode(), что необязательно.)

Примечание: К сожалению, ссылка на значение напрямую не указана: $data['12'] приведет к уведомлению.

Update:
Из PHP 7.2 на нем также можно использовать цифровую строку в качестве ключа для ссылки на значение:

var_dump($data['12']); // int 32 
+1

Прямой доступ к значению с помощью строкового ключа не работает. Добавьте эту строку в свой пример: 'echo $ data ['12 '];'. Он даст ошибку: «Примечание: неопределенное смещение: 12 in - on line 5». –

+0

Да, ты прав. Предполагая, что это возможно иногда в прошлом. – David

+0

, когда U использует laravel dd ($ data), он потерпит крах: P –

1

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

НЕПРАВИЛЬНО

У меня есть функция литья, которая обрабатывает последовательную ассоциативную литью массива,

$array_assoc = cast($arr,'array_assoc'); 

$array_sequential = cast($arr,'array_sequential'); 

$obj = cast($arr,'object'); 

$json = cast($arr,'json'); 



function cast($var, $type){ 

    $orig_type = gettype($var); 

    if($orig_type == 'string'){ 

     if($type == 'object'){ 
      $temp = json_decode($var); 
     } else if($type == 'array'){ 
      $temp = json_decode($var, true); 
     } 
     if(isset($temp) && json_last_error() == JSON_ERROR_NONE){ 
      return $temp; 
     } 
    } 
    if(@settype($var, $type)){ 
     return $var; 
    } 
    switch($orig_type) { 

     case 'array' : 

      if($type == 'array_assoc'){ 

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

      } else if($type == 'array_sequential'){ 

       return array_values($var); 

      } else if($type == 'json'){ 

       return json_encode($var); 
      } 
     break; 
    } 
    return null; // or trigger_error 
} 
0

Что касается @David решения, пожалуйста, обратите внимание, что при попытке получить доступ к строковым значениям в ассоциативный массив, числа не будут работать.Я предполагаю, что они отлиты целыми числами за кулисами (при доступе к массиву), и никакое значение не найдено. Доступ к значениям в виде целых чисел также не будет работать. Но вы можете использовать array_shift() для получения значений или итерации массива.

$data = new stdClass; 
$data->{"0"} = "Zero"; 
$data->{"1"} = "One"; 
$data->{"A"} = "A"; 
$data->{"B"} = "B"; 

$data = (array)$data; 

var_dump($data); 
/* 
Note the key "0" is correctly saved as a string: 
array(3) { 
    ["0"]=> 
    string(4) "Zero" 
    ["A"]=> 
    string(1) "A" 
    ["B"]=> 
    string(1) "B" 
} 
*/ 

//Now let's access the associative array via the values 
//given from var_dump() above: 
var_dump($data["0"]); // NULL -> Expected string(1) "0" 
var_dump($data[0]); // NULL (as expected) 
var_dump($data["1"]); // NULL -> Expected string(1) "1" 
var_dump($data[1]); // NULL (as expected) 
var_dump($data["A"]); // string(1) "A" (as expected) 
var_dump($data["B"]); // string(1) "B" (as expected) 
Смежные вопросы