私が配列を持っているとすると:
$array = array(
'a' => array(
'b' => array(
'c' => 'hello',
),
),
'd' => array(
'e' => array(
'f' => 'world',
),
),
);
キーを区切り文字(この例の場合はスラッシュ/
)で連結して、参照の1次元ルックアップに「フラット化」したいと思います。
成功した出力でを実行するvar_dump()
と、次のようになります:(すべての参照に注意してください)
array(6) {
["a"]=>
&array(1) {
["b"]=>
&array(1) {
["c"]=>
&string(5) "hello"
}
}
["a/b"]=>
&array(1) {
["c"]=>
&string(5) "hello"
}
["a/b/c"]=>
&string(5) "hello"
["d"]=>
&array(1) {
["e"]=>
&array(1) {
["f"]=>
&string(5) "world"
}
}
["d/e"]=>
&array(1) {
["f"]=>
&string(5) "world"
}
["d/e/f"]=>
&string(5) "world"
}
array(2) {
["a"]=>
&array(1) {
["b"]=>
&array(1) {
["c"]=>
&string(5) "hello"
}
}
["d"]=>
&array(1) {
["e"]=>
&array(1) {
["f"]=>
&string(5) "world"
}
}
}
現状では、私はこれを使用しています:
function build_lookup(&$array, $keys = array()){
$lookup = array();
foreach($array as $key => &$value){
$path = array_merge($keys, (Array) $key);
$lookup[implode('/', $path)] = &$value;
if(is_array($value)){
$lookup = array_merge($lookup, build_lookup($value, $path));
}
}
return $lookup;
}
ただし、再帰の要素を削除することで改善しようとしています(スタック/ポップアプローチに切り替えます)。そうすることの問題は、次のような典型的な再帰から非再帰へのアプローチとしての参照の保存です。
$stack = $input;
while(!empty($stack)){
$current = array_pop($stack);
// do stuff and push to stack;
}
...参照で失敗します。
私はSOについていくつかの同様の質問/回答を見てきましたが、どれも参照を適切に扱っていませんでした(それは質問者の意図ではなかったため)
ここでより良い(より速く読む)アプローチはありますか?
最終的な解決策(@chrisに感謝):
/**
*
* @return array
*/
public function get_lookup_array()
{
$stack = $lookup = array();
try
{
foreach($this->_array as $key => &$value)
{
$stack[$key] = &$value;
}
while(!empty($stack))
{
$path = key($stack);
$lookup[$path] = &$stack[$path];
if(is_array($lookup[$path]))
{
foreach($lookup[$path] as $key => &$value)
{
$stack[$path . $this->_separator . $key] = &$value;
}
}
unset($stack[$path]);
}
}
catch(\Exception $exception)
{
return false;
}
return $lookup;
}