让我假装我有这个:
$str = "/a/b/c/d/";
$arr = array_filter( explode("/", $str );
此时$arr
包含4个元素。有没有办法可以在包含这4个元素的数组中创建路径,例如:
$result = [
"a" => [
"b" => [
"c" => [
"d" => [
]
]
]
]
]
...没有迭代$arr
?
我知道
$x["a"]["b"]["c"]["d"] = 1;
完全有效,即使$x
未被声明为数组,它也会创建一个4级数组,所以我所要求的应该是可能的。
答案 0 :(得分:1)
我不建议这样做,因为使用eval()
时会产生安全隐患。但是,因为我在评论中说过没有迭代就无法完成,我觉得有必要将此作为答案发布(是的,我知道implode()
在内部进行迭代)。
$str = "/a/b/c/d/";
$arr = array_filter( explode("/", $str ));
$keys = '["'.implode('"]["', $arr).'"]';
eval('$x'.$keys.' = 1;');
print_r($x);
更实际的方法请参阅How to write getter/setter to access multi-leveled array by dot separated key names?
答案 1 :(得分:1)
我曾写过一次函数,将此行为视为副作用。它不迭代,但使用递归。
请参阅:https://github.com/feeela/php-utils/blob/master/function.getArrayValueReference.php
你可以这样打电话:
<?php
$newArray = array();
$keys = 'a/b/c/d';
$referenceToD =& getArrayValueReference( $newArray, explode( '/', $keys ), true );
$referenceToD[0] = 'foo';
$referenceToD[1] = 'bar';
print_r( $newArray );
这会修改数组$newArray
并创建所有级别。函数返回值是对最后一个键的引用(该示例中为“d”)。
...导致:
Array (
[a] => Array (
[b] => Array (
[c] => Array (
[d] => Array (
[0] => foo
[1] => bar
)
)
)
)
)
答案 2 :(得分:0)
如果没有迭代它,就无法使用$arr
的所有值。
我想你不想写一个foreach
循环但是使用一些PHP函数为你做迭代。
这是一个可能的解决方案:
$x = array_reduce(
array_reverse($arr),
function ($carry, $item) {
return [$item => $carry];
},
1
);
它产生的结果与:
相同$x = [];
$x['a']['b']['c']['d'] = 1;
不幸的是,它会重复$arr
两次(array_reverse()
和array_reduce()
)。
使用对象(stdClass
)而不是数组生成所需嵌入的另一种方法:
$out = new stdClass;
array_reduce(
$arr,
function ($carry, $item) {
$v = new stdClass;
$carry->{$item} = $v;
return $v;
},
$out
);
它使用$arr
上的单个迭代工作,但它依赖于在PHP中处理对象的工作方式(这不适用于数组)。
PHP处理对象的方式使它们看起来像是通过引用传递的。这是一个常见的误解,即物体是通过参考传递的。在PHP但this is not true。双重间接负责此行为。
function makeArray(array $arr, $initial)
{
if (! count($arr)) {
return $initial;
} else {
$key = array_shift($arr);
return [ $key => makeArray($arr, $initial) ];
}
}
$out = makeArray($arr, 1);
此解决方案仅在数组上迭代一次并生成数组层次结构,但递归性对于大型输入数组来说是灾难性的,因为它使用了大量内存。