Числовая строка как ключ массива в PHP


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

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

печать

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

Я хочу

array(1) {
  ["123"]=>
  int(1)
}
11 90
php

11 ответов:

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

С руководство:

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

дополнительное соглашение

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

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

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

Да, это возможно путем array-casting an

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

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

мое решение:

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

пробел char (prepend) является хорошим решением, потому что сохранить преобразование int:

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

вы увидите 55 как int.

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

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

из руководства PHP:

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

строки, содержащие допустимые целые числа, будут приведены к целочисленному типу. Например, ключ " 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
}

как обходной путь, вы можете кодировать PHP массив в объект json, с опцией JSON_FORCE_OBJECT.

т. е., это пример:

     $a = array('foo','bar','baz');
     echo "RESULT: ", json_encode($a, JSON_FORCE_OBJECT);

в результате:

     RESULT: {"0" : "foo", "1": "bar", "2" : "baz"}

я столкнулся с этой проблемой на массиве с' 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";
    }
}

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

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

вы можете обойти это, используя . Довольно прямо вперед, но я не думал об этом сначала ^^.

Что касается решения @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)

У меня была эта проблема при попытке отсортировать массив, где мне нужен ключ сортировки, чтобы быть шестнадцатеричным 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];