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

时间:2010-08-10 04:08:10

标签: php arrays

我遇到过一个使用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()仍然将它们显示为整数数组索引。

有没有办法强制键成为字符串,所以我可以重新排序它们而不会破坏数组?

9 个答案:

答案 0 :(得分:12)

你可以'

  

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

返回一个数组,其中包含来自数组小写或大写的所有键。 编号索引保持原样

我接下来的尝试是通过array_combine旧值(新的(字符串)键)创建一个新数组。

我尝试了几种使$keys数组包含string类型数值的方法。

range("A", "Z" )适用于字母表,所以我会尝试使用数字字符串。

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

编辑:

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

所有这一切

答案 1 :(得分:9)

怎么样?

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

编辑: 也试过了,是的,它不起作用。

来自PHP docs

  

键可以是整数,也可以是   串。如果一把钥匙是标准   表示整数,它会   被解释为这样(即“8”将   被解释为8,而“08”将被解释为   被解释为“08”)。浮在钥匙上   被截断为整数。没有   不同的索引和关联   PHP中的数组类型;只有一个   数组类型,它们都可以包含   整数和字符串索引。

我想现在这取决于你想如何对数组进行排序。 (最终输出?)

答案 2 :(得分:8)

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

答案 3 :(得分:7)

修改

  

我认为如果他们是整数,我   无法改变而无法重新排序   关键(这在此很重要   例)。但是,如果是的话   字符串,我可以重新排序他们如何   像索引一样不应该   被解释为有任何特殊之处   含义。无论如何,请看我的问题   更新我是如何做到的(我去了一个   不同的路线)。

实际上他们不一定要按数字顺序......

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

答案 4 :(得分:4)

您可以将空字符"\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()也不会显示在那里&#39 ;最后是一个空字符,对于你为何得到&#34;未定义的偏移&#34;没有任何线索。因此,如果通过foreach()进行迭代,或者最终维护您的代码会讨厌您,只能使用此hack。

答案 5 :(得分:3)

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

它可能不是完全最优的,但它允许您对数组进行排序并提取(相当于)原始密钥,而不必截断任何内容。

答案 6 :(得分:0)

编辑: 这应该工作

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

答案 7 :(得分:0)

只有一位评论者说得对,接受的答案是asort()uasort()arsort()是内置插件,可以在保持关键关联的同时对数组进行排序,并且自版本4以来它们已经存在.RTFM,人。

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

答案 8 :(得分:0)

嗨,我们可以使用以下方法将数组的索引设置为字符串。如果我们将数组转换为xml,则类似[0]的索引可能会产生问题,因此请转换为类似[sample_0]的字符串

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