如何强制PHP使用字符串作为数组键?[duplicate]

ghhkc1vu  于 2022-11-28  发布在  PHP
关注(0)|答案(8)|浏览(238)

此问题在此处已有答案

A numeric string as array key in PHP(11个答案)
两年前就关门了。
机构群体在12个月前审查了是否重新讨论此问题,并将其关闭:
原始关闭原因未解决
我遇到过一个老的应用程序,它使用id来命名类型数组,例如...

array(1) {
  [280]=>
  string(3) "abc"
}

现在我需要重新排序这些键,如果键是整数,var_dump()会使它看起来不会发生。
如果我给每个索引添加一个avar_dump()将在键周围显示双引号,我猜现在它是一个字符串...

array(1) {
  ["280a"]=>
  string(3) "abc"
}

这将使我可以轻松地重新排序它们,而不必接触更多的代码。
这是行不通的

$newArray = array();
foreach($array as $key => $value) {
   $newArray[(string) $key] = $value;
}

var_dump()仍然将它们显示为整数数组索引。
有没有办法强制键成为字符串,这样我就可以在不破坏数组的情况下重新排序它们?

wa7juj8i

wa7juj8i1#

"你不能“
包含有效整数的字符串将被转换为整数类型。例如,键“8”实际上将存储在8下。另一方面,“08”将不会被转换,因为它不是有效的十进制整数。
编辑:

事实上你可以!!Cast sequential array to associative array

$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数组包含string类型的数值。
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.

将键更改为字符串并保持其文字值的唯一方法是在键前加上后缀it,后缀it带有小数点"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"

编辑:

事实上你可以!!Cast sequential array to associative array

这一切都是徒劳

jv4diomz

jv4diomz2#

使用对象而不是数组$object = (object)$array;

ndh0cuux

ndh0cuux3#

你可以在数组键的末尾添加空字符"\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()也不会告诉你结尾有一个空字符,所以没有任何线索说明为什么你会得到“未定义的偏移量”。所以,只有在通过foreach()迭代时才使用这个方法,否则维护你代码的人会讨厌你。

ffvjumwh

ffvjumwh4#

编辑

我假设如果它们是整数,我不能在不改变键的情况下对它们重新排序(这在这个例子中很重要)。然而,如果它们是字符串,我可以按照它们喜欢的方式对它们重新排序,因为索引不应该被解释为有任何特殊的含义。无论如何,看看我的问题更新,我是如何做到的(我走了一条不同的路线)。
实际上,它们不必按数字顺序排列...

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
1bqhqjot

1bqhqjot5#

我可以通过在每个键的末尾添加“.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)
它可能不是完全最佳的,但它确实允许您对数组进行排序并提取(相当于)原始键,而不必截断任何内容。

jslywgbw

jslywgbw6#

编辑:这应该可以

foreach($array as $key => $value) { 
    $newkey = sprintf('%s',$key);
    $newArray["'$newkey'"] = $value; 
}
bvn4nwqk

bvn4nwqk7#

我们可以用下面的方法把数组的索引变成一个字符串。如果我们把一个数组转换成xml,那么像[0]这样的索引可能会产生问题,所以转换成像[sample_0]这样的字符串

$newArray = array();
foreach($array as $key => $value) {
   $newArray["sample_".$key] = $value;
}
vyu0f0g1

vyu0f0g18#

到目前为止,所有其他的答案都是一些黑客,要么使用脆弱的变通方法,可能会在主要的PHP版本之间中断,要么故意破坏键,造成不必要的陷阱,要么只是毫无益处地降低代码速度。从PHP 4开始就有各种函数对数组进行排序,同时维护关键的键关联。
实际上没有必要阻止PHP使用整数键,它只在整数表示与字符串完全相同时才这样做,因此当从数组阅读时,将整数键转换回字符串保证返回原始数据。证明:

<?php

# use string keys to define as populating from a db, etc. would
$in = array(
  '347' => 'ghi',
  '176' => 'def',
  '280' => 'abc',
);

# sort by key
ksort($in);
echo "K:\n";
$i = 1;
foreach ($in as $k => $v) {
    echo $i++, "\n";
    $k = (string) $k; # convert back to original
    var_dump($k, $v);
}

# sort by value
asort($in, SORT_STRING);
echo "\nV:\n";
$i = 1;
foreach ($in as $k => $v) {
    echo $i++, "\n";
    $k = (string) $k;
    var_dump($k, $v);
}

# unnecessary to cast as object unless keys could be sequential, gapless, and start with 0
if (function_exists('json_encode')) {
    echo "\nJSON:\n", json_encode($in);
}

产生:

Output for 5.2.0 - 5.2.17, 5.3.0 - 5.3.29, 5.4.0 - 5.4.45, 5.5.0 - 5.5.38, 5.6.0 - 5.6.40, 7.0.0 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.34, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.26, 8.1.0 - 8.1.13, 8.2rc1 - rc3
    K:
    1
    string(3) "176"
    string(3) "def"
    2
    string(3) "280"
    string(3) "abc"
    3
    string(3) "347"
    string(3) "ghi"

    V:
    1
    string(3) "280"
    string(3) "abc"
    2
    string(3) "176"
    string(3) "def"
    3
    string(3) "347"
    string(3) "ghi"

    JSON:
    {"280":"abc","176":"def","347":"ghi"}

Output for 4.3.0 - 4.3.11, 4.4.0 - 4.4.9, 5.0.0 - 5.0.5, 5.1.0 - 5.1.6
    K:
    1
    string(3) "176"
    string(3) "def"
    2
    string(3) "280"
    string(3) "abc"
    3
    string(3) "347"
    string(3) "ghi"

    V:
    1
    string(3) "280"
    string(3) "abc"
    2
    string(3) "176"
    string(3) "def"
    3
    string(3) "347"
    string(3) "ghi"

相关问题