一个数字字符串作为PHP中的数组键


104

是否可以"123"在PHP数组中使用数字字符串作为键,而无需将其转换为整数?

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

版画

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

我想要

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

7
由于PHP是松散类型的,因此几乎所有目的"123"== 123。您为什么要专门将其作为字符串(并且拥有int不好)的原因是什么?
ircmaxell,2010年

17
我想到的原因与数组函数有关,例如array_merge “如果输入数组具有相同的字符串键,则该键的后一个值将覆盖前一个键。但是,如果数组包含数字键,则后一个值将不覆盖原始值,但将被附加。”
ficuscr 2014年

8
另一个示例,其中数字字符串作为数组键是有问题的:asort
swenedo 2015年


4
另一个用例:单元测试JSON数据转换。将这样的数组转换为JSON并返回,将不能使您断言原始数组和结果都完全相同。
大卫,

Answers:


90

没有; 不,这不对:

手册

键可以是整数或字符串。如果键是整数的标准表示,它将被解释为整数(即​​“ 8”将被解释为8,而“ 08”将被解释为“ 08”)。

附录

由于下面的评论,我认为指出该行为 JavaScript对象键相似但不相同很有趣。

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

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

107
PHP,服务器端IE。
Marek Maurizio

5
看来实际上有办法!您不同意这个答案吗?stackoverflow.com/a/35180513/247696
Flimm

1
怎么样?!.. foo [012]返回“栏”
Himanshu

2
@Himanshu:因为php将以0开头的数字解释为八进制。所以012是八进制10
Yeasir阿拉法特Majumder

49

是的,可以通过数组广播stdClass对象来实现:

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

这样就可以为您提供(PHP 7.1之前的版本):

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

(更新:我的原始答案显示了使用json_decode()json_encode()不是必需的更复杂的方法。)

请注意以下注释:不幸的是,无法直接引用该值:$data['12']会导致通知。

更新
从PHP 7.2开始,还可以使用数字字符串作为键来引用值:

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

2
但是,使用字符串键直接访问值不起作用。将此行添加到您的示例中:echo $data['12'];。它将出现错误“注意:未定义的偏移量:12 in-第5行”。
LS

1
当您使用laravel dd($ data)时,它会崩溃:P
KamilKiełczewski17年

2
在PHP 7.2.0RC2中,行为与以前相同。
dev0

1
显然array_key_exists,在旧版本中也找不到。
不要惊慌'18

1
在php 7.4中不起作用
茉莉花

12

如果您需要在php数据结构中使用数字键,则可以使用一个对象。对象保持顺序,因此可以进行迭代。

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

这是一个很好的建议。我正在编写框架代码,面对一个传递可能具有“意外”索引的数组的人:array('this','that')或“ associative” indexing:array(123 => array('this','that '))。现在,感谢您,我可以输入提示;)+1
Just Plain High

但是是否可以在PHP数组中使用“ 123”之类的数字字符串作为键,而无需将其转换为整数?
Flimm

@Flimm不,那是不可能的,这就是为什么我提供我的解决方案。
蒸汽动力

@Flimm答案似乎与PHP手册矛盾:包含有效整数的字符串将转换为整数类型。例如,键“ 8”实际上将存储在8以下。另一方面,“ 08”将不是强制转换,因为它不是有效的十进制整数。,尽管我尚未检验他的答案。
蒸汽动力

该句子位于“ Specify with”(指定为)下array(),因此我假设在这种情况下,将指定有效整数的字符串转换为整数类型。但是事实证明,还有其他方法可以创建数组,但不会发生这种情况,例如我测试过的大卫的答案
Flimm

10

我的解决方法是:

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

空格字符(前置)是一个很好的解决方案,因为保持int转换:

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

您会看到55为int。


4
或者"0$id" => $value。在0作品之前。
nawfal 2015年

因此,您要说的是,如果不将数字字符串“ 123”转换为整数,就不可能将其用作PHP数组中的键?
Flimm

5

您可以将键类型转换为字符串,但是由于PHP的松散输入,最终会将其转换为整数。你自己看:

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

从PHP手册中:

键可以是整数或字符串。如果键是整数的标准表示形式,它将被解释为这样(即“ 8”将被解释为8,而“ 08”将被解释为“ 08”)。键中的浮点数将被截断为integer。索引数组和关联数组类型与PHP中的类型相同,都可以包含整数索引和字符串索引。


1
转换不是由于宽松的输入;php确定字符串是否看起来是数字,然后将其转换。
2013年

1
那你是说不可能吗?该答案表明,有一种方法可以使用看起来像整数的字符串作为数组中的键。
Flimm

恕我直言,问题是PHP解释器。甚至不可能想象有一种将字符串和整数混合为数组键的语言。最好的解决方案?正如Undolog stackoverflow.com/a/15413637/1977778所建议的那样,最好的解决方案是使用尾随空格。
森坦扎'16

@sentenza:它可以设想,特别是因为PHP允许字符串和整数的混合物作为数组的键:[42 => 'answer', 'snafu' => 'fubar']
LS

@LS是的。我知道PHP允许您这样做,但是如果您考虑一个假设的泛型类型系统中的键,它将不会与同时包含字符串和数字的任何混合类型匹配。应用于关联数组的键的松散类型很容易出错。
森坦扎'16

1

我在尝试合并同时具有字符串键和整数键的数组时遇到了这个问题。重要的是,整数也应作为字符串处理,因为它们是输入字段的名称(如鞋码等)。

当我使用$data = array_merge($data, $extra);PHP时会“重新排序”键。在试图做排序,整数键(我试过6- '6'- "6"即使(string)"6"钥匙)从0得到了重新命名为n ...如果你想想看,在大多数情况下,这将是所期望的行为。

您可以通过使用$data = $data + $extra;替代方法来解决此问题。挺直截了当的,但是起初我没有想到它。


完全相同的问题将我带到了此页面,但是我不得不说这不是对OP的回答。
Flimm

@Flimm是的。但是寻找答案将我带到了此页面。我认为我的解决方案可能会对其他Google员工有所帮助:)
Brainfeeder '16

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
}

在php 7.4中不起作用
茉莉花

1

解决方法是,可以使用JSON_FORCE_OBJECT选项将PHP数组编码为json对象。

即,这个例子:

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

将导致:

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

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

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)

哪个PHP版本?我完全尝试了您的示例,并且密钥"0"变为0php 7.2.10
J.BizMai

-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];

那么,您是说不能将数字字符串“ 123”用作PHP数组中的键,而不能将其转换为整数吗?
Flimm

否-在使用kso​​rt()对数组进行排序时,它仅将所有数字的键视为整数-不会转换为整数-在排序过程中仅将其作为一个比较。
drchuck
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.