在 PHP 中作为数组键的数字字符串

A numeric string as array key in PHP

提问人:Dogbert 提问时间:11/5/2010 更新时间:11/17/2022 访问量:101232

问:

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

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

指纹

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

我想要

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

评论

9赞 ircmaxell 11/5/2010
由于 PHP 是松散类型的,因此 == 几乎用于所有目的。你特别希望它作为一个字符串的原因是什么(并且有一个 int 是不好的)?"123"123
23赞 ficuscr 11/6/2014
我想到的原因与数组函数有关,例如“如果输入数组具有相同的字符串键,则该键的后一个值将覆盖前一个值。但是,如果数组包含数字键,则后面的值不会覆盖原始值,而是会附加。array_merge
9赞 swenedo 1/14/2015
另一个将数字字符串作为数组键存在问题的示例:asort
2赞 nawfal 11/18/2015
如何强制PHP使用字符串作为数组键的可能重复?
5赞 David 2/3/2016
另一个用例:单元测试 JSON 数据转换。将这样的数组转换为 JSON 并返回不会让您断言原始数组和结果完全相同。

答:

5赞 bcosca 11/5/2010 #1

您可以将键类型转换为字符串,但由于 PHP 的松散类型,它最终会转换为整数。亲眼看看:

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

从PHP手册:

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

评论

1赞 Ja͢ck 4/9/2013
转换不是由于松散的打字;PHP 确定字符串是否看起来是数字,然后对其进行转换。
1赞 Flimm 4/19/2016
所以你是说这是不可能的吗?这个答案表明,有一种方法可以使用看起来像整数的字符串作为数组中的键。
0赞 sentenza 5/19/2016
恕我直言,问题出在PHP解释器上。甚至无法想象有一种将字符串和整数混合为数组键的语言。最好的解决方案?正如 Undolog 所建议的那样 stackoverflow.com/a/15413637/1977778 最好的解决方案是使用尾随空格......可悲的是。
0赞 Mr. Lance E Sloan 5/29/2016
@sentenza:可以想象,特别是因为PHP允许字符串和整数的混合作为数组的键:[42 => 'answer', 'snafu' => 'fubar']
0赞 sentenza 5/31/2016
@LS是的。我知道 PHP 允许你这样做,但如果你考虑假设的泛型类型系统中的键,它将不匹配任何同时包含字符串和数字的混合类型。应用于关联数组键的松散类型很容易出错。
101赞 Hamish 11/5/2010 #2

洛伊不,不是:

手册:

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

补遗

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

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

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

评论

5赞 Flimm 4/19/2016
看起来有办法,实际上!你不同意这个答案吗?stackoverflow.com/a/35180513/247696
1赞 Himanshu 10/24/2018
如何?!。。foo[012] 返回“bar”
4赞 Yeasir Arafat Majumder 4/16/2020
@Himanshu:因为 PHP 将以 0 开头的数字解释为八进制。所以 012 是八进制 10。
0赞 Darshit Mendapara 6/25/2021
是的,可以使用以下代码:$dtmf_arr = array();foreach ($_POST['dtmf'] 作为 $val) { $dtmf_arr['“'.$val.'”'] = $dtmf[$val]; }
0赞 Walf 12/1/2022
此外,还有很多方法可以解决这个问题,例如使用数组添加而不是合并,或者使用许多保留键的内置函数。如果在从数组中读取时再次需要将键作为字符串,则将其转换为字符串可以保证返回原始值。+
12赞 steampowered 9/20/2011 #3

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

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

评论

0赞 12/8/2013
这是一个很好的建议。我正在编写框架代码,并面对有人传递一个数组,该数组可能具有“意外”索引:array('this', 'that') 或“关联”索引:array(123=>array('this', 'that'))。现在,多亏了你,我只能输入提示 ;) +1
0赞 Flimm 4/19/2016
但是是否可以使用像“123”这样的数字字符串作为 PHP 数组中的键,而不会将其转换为整数?
0赞 steampowered 4/19/2016
@Flimm不,这是不可能的,这就是我提供解决方案的原因。
0赞 steampowered 4/19/2016
@Flimm这个答案似乎与PHP手册相矛盾:包含有效整数的字符串将被强制转换为整数类型。 例如,键“8”实际上将存储在 8 下。另一方面,“08”不会被强制转换,因为它不是一个有效的十进制整数,尽管我没有测试他的答案。
0赞 Flimm 4/19/2016
该句子位于“指定 ”部分下,因此我假设在该上下文中,指定有效整数的字符串将被转换为整数类型。但事实证明,还有其他创建数组的方法,但不会发生这种情况,例如在 David 的回答中,我已经测试过了。array()
0赞 fisharebest 1/22/2013 #4

我在同时使用“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 4/19/2016
这并不是这个问题的真正答案。
13赞 Undolog 3/14/2013 #5

我的解决方法是:

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

空格 char (prepend) 是一个很好的解决方案,因为保持 int 转换:

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

您会看到 55 为 int。

评论

4赞 nawfal 11/18/2015
阿恩。前面也有作品。"0$id" => $value0
0赞 Flimm 4/19/2016
所以你是说不可能使用像“123”这样的数字字符串作为 PHP 数组中的键,而不将其转换为整数?
0赞 Danon 12/16/2020
@Flimm 是的,这是不可能的。反正不是类型。array
3赞 Brainfeeder 3/20/2015 #6

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

当我使用PHP时,会“重新排序”键。在尝试进行排序时,整数键(我尝试使用 - - 甚至作为键)从 0 重命名为 ...如果你仔细想想,在大多数情况下,这将是理想的行为。$data = array_merge($data, $extra);6'6'"6"(string)"6"n

您可以通过改用来解决此问题。 很简单,但我一开始没有想到^^。$data = $data + $extra;

评论

1赞 Flimm 4/19/2016
完全相同的问题将我带到了这个页面,但我不得不说这不是 OP 问题的答案。
0赞 Brainfeeder 4/19/2016
@Flimm 真的。但是寻找答案将我带到了这个页面。我认为我的解决方案可以对其他 Google 员工有所帮助:)
-1赞 drchuck 12/23/2015 #7

我在尝试对数组进行排序时遇到了这个问题,其中我需要排序键是十六进制 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赞 Flimm 4/19/2016
那么你是说不可能使用像“123”这样的数字字符串作为 PHP 数组中的键,而不将其转换为整数?
0赞 drchuck 4/21/2016
不 - 在使用 ksort() 对数组进行排序时,它只将所有数字的键视为整数 - 它永远不会转换为整数 - 只是在排序过程中作为一个进行比较。
59赞 David 2/3/2016 #8

是的,可以通过数组转换对象来实现: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

评论

3赞 Mr. Lance E Sloan 5/29/2016
但是,使用字符串键直接访问值不起作用。将以下行添加到示例中:。它将给出错误,“注意:未定义的偏移量:12 in - 在第 5 行”。echo $data['12'];
1赞 Kamil Kiełczewski 3/1/2017
当你使用 laravel dd($data) 时,它会崩溃:P
2赞 dev0 9/19/2017
在 PHP 7.2.0RC2 中,行为与以前相同。
2赞 Don't Panic 8/30/2018
显然也不会在旧版本中找到它。array_key_exists
1赞 Tomáš Fejfar 7/4/2022
这仅适用于 >5.0 <7.1.33
0赞 TarranJones 5/12/2016 #9

包含有效整数的字符串将被强制转换为整数类型。例如,键“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
}

评论

2赞 geoffs3310 10/14/2022
这是行不通的。如果键是有效的整数,则关联数组键仍将是整数
0赞 Nico Schefer 6/2/2017 #10

关于@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)

评论

0赞 J.BizMai 12/19/2018
哪个php版本?我完全尝试了您的示例,并且密钥变成了 php 。"0"07.2.10
1赞 GigiManco 3/30/2018 #11

作为解决方法,您可以使用 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赞 Walf 12/1/2022
需要注意的是,它还将强制所有子数组都是可能不会产生预期输出的对象,请参阅 json_encode($a, JSON_FORCE_OBJECT) 和 json_encode((object) $a) 之间的区别