如何强制PHP将字符串用作数组键?

我遇到了一个使用ID来命名类型数组的旧应用,例如...

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

现在,我需要对它们进行重新排序,并且var_dump()会使键为整数,这似乎不会发生。

如果我向每个索引添加var_dump(),则var_dump()会在键周围显示双引号,我想显示它现在是一个字符串...

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

这使我可以轻松地对它们进行重新排序,而无需触及更多代码。

这是行不通的。

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

var_dump()仍将其显示为整数数组索引。

有没有一种方法可以将键强制为字符串,这样我就可以在不破坏数组的情况下对其重新排序?

alex asked 2019-11-17T21:47:25Z
7个解决方案
15 votes

你不能!

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

编辑:

其实你可以的!将顺序数组转换为关联数组

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

在大多数情况下,以下内容引用了它。

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

此示例来自PHP Docs

 <?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. 

返回一个数组,其中所有键均使用小写或大写字母。 编号索引保持不变。

我的下一个尝试是通过"00","01","02"544将旧值使用新(字符串)键创建一个新数组。

我尝试了几种使"00","01","02"数组包含字符串类型的数值的方法。

"00","01","02"适用于字母,因此尽管我会尝试使用数字字符串来尝试。

$keys = range("0", (string) count($arr) ); // integers

这导致了一个充满键的数组,但是都是int类型的。

这是创建具有string类型值的数组的几次成功尝试。

$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. 

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

编辑:

其实你可以的!将顺序数组转换为关联数组

一无所有

TarranJones answered 2019-11-17T21:50:40Z
8 votes

编辑:

我假设如果它们是整数,我   不能改变他们的顺序而不改变   关键(在此意义重大   例)。 但是,如果他们是   字符串,我可以重新排序它们   就像索引不应该   解释为有特殊之处   含义。 反正看我的问题   更新我的操作方式(我失败了   不同的路线)。

实际上,它们不必按数字顺序...

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
prodigitalson answered 2019-11-17T21:47:58Z
8 votes

使用对象代替数组$object = (object)$array;

Paul-Emile MINY answered 2019-11-17T21:51:04Z
5 votes

您可以将空字符$numbers["444"]附加到数组键的末尾。 这使得PHP无法将字符串解释为整数。 所有数组函数(例如$numbers["444\0"])都可以在其上工作。 同样也不是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"
}

没有$numbers["444"]部分,结果数组将是:

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"
}

另外$numbers["444"]也将忽略空字符,这意味着$numbers["444\0"]var_dump()在排序算法中将具有相同的权重。

此方法的唯一缺点是要进行访问,例如$numbers["444"],实际上您必须通过$numbers["444\0"]对其进行访问,因为甚至没有var_dump()会在末尾显示一个空字符,因此没有任何关于为什么得到“未定义”的线索 抵消”。 因此,仅当通过foreach()进行迭代或最终维护您的代码的人会讨厌您时,才使用此hack。

Tim Aagaard answered 2019-11-17T21:51:58Z
3 votes

我可以通过在每个键的末尾添加“ .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)

它可能并非完全最佳,但它确实允许您对数组进行排序并提取(等效)原始键,而不必截断任何内容。

NeuroXc answered 2019-11-17T21:52:37Z
0 votes

编辑:这应该工作

foreach($array as $key => $value) { 
    $newkey = sprintf('%s',$key);
    $newArray["'$newkey'"] = $value; 
} 
user387302 answered 2019-11-17T21:53:02Z
0 votes

只有一位评论者有此权利,并且被接受的答案是错误的。 (string) $keyuasort()arsort()是内置插件,它们在对数组进行排序的同时保持键关联,并且自版本4开始就存在。RTFM,人们。

不要通过弄乱键来逃避/破坏数据。 您无法阻止PHP使用整数键,因此请不要尝试。 仅当整数表示形式与字符串完全相同时,才会发生这种情况,因此,当从数组中读取键和值(即(string) $key)时,只需对它们进行强制转换即可。您可以使用上述函数进行所有需要的排序操作。

Walf answered 2019-11-17T21:53:35Z
translate from https://stackoverflow.com:/questions/3445953/how-can-i-force-php-to-use-strings-for-array-keys