将多维关联数组展平为PHP中的一个一维引用数组 [英] Flatten multidimensional associative array to one one-dimensional array of references in PHP

查看:41
本文介绍了将多维关联数组展平为PHP中的一个一维引用数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于我有一个数组:

$array = array(
    'a' => array(
        'b' => array(
            'c' => 'hello',
        ),
    ),
    'd' => array(
        'e' => array(
            'f' => 'world',
        ),
    ),
);

我想将其压平"为参考的一维查找,将键与定界符(在本例中为,正斜杠/ )连接起来

I want to "flatten" it to a single dimension look-up of references, concatenating keys with a delimiter (in the case of this example, a forward slash /)

在成功的输出上执行var_dump()会产生:(请注意所有引用)

Performing a var_dump() on a successful output would yield: (note all the references)

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

就目前而言,我正在使用它:

As it stands, I'm using this:

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

但是,我试图通过删除递归元素来对此进行改进(切换到堆栈/弹出方法),这样做的问题是引用保留,这是典型的递归-非递归方法:

However, I'm trying to improve on it by removing the element of recursion (switching to a stack/pop approach) The problem with doing so is reference preservation, as the typical recursion-to-non-recursion approach of:

$stack = $input;
while(!empty($stack)){
    $current = array_pop($stack);
    // do stuff and push to stack;
}

...没有引用.

我已经看到了一些关于SO的类似问题/答案,尽管都没有对引用进行适当的处​​理(因为这不是提问者的意图)

I've seen a few similar questions/answers on SO, though none of which dealt appropriately with references (as it wasn't the asker's intent)

这里是否有更好的(阅读速度更快的)方法?

Is there a better (read faster) approach here?

最终的解决方案(感谢@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;
}

推荐答案

header('content-type:text/plain');

$arr = array(
    'a' => array(
        'b' => array(
            'c' => 'hello',
        ),
    ),
    'd' => array(
        'e' => array(
            'f' => 'world',
        ),
    ),
);

//prime the stack using our format
$stack = array();
foreach ($arr as $k => &$v) {
    $stack[] = array(
        'keyPath' => array($k),
        'node' => &$v
    );
}

$lookup = array();

while ($stack) {
    $frame = array_pop($stack);
    $lookup[join('/', $frame['keyPath'])] = &$frame['node'];
    if (is_array($frame['node'])) {
        foreach ($frame['node'] as $key => &$node) {
            $keyPath = array_merge($frame['keyPath'], array($key));
            $stack[] = array(
                'keyPath' => $keyPath,
                'node' => &$node
            );
            $lookup[join('/', $keyPath)] = &$node;
        }
    }
}


var_dump($lookup);
// check functionality
$lookup['a'] = 0;
$lookup['d/e/f'] = 1;
var_dump($arr);

或者,您可以做类似的事情以获得参考/w array_pop功能

Alternatively you could have done stuff like this to get a reference /w array_pop functionality

end($stack);
$k = key($stack);
$v = &$stack[$k];
unset($stack[$k]);

之所以可行,是因为php数组具有按键创建时间排序的元素. unset()删除密钥,从而重置该密钥的创建时间.

That works because php arrays have elements ordered by key creation time. unset() deletes the key, and thus resets the creation time for that key.

这篇关于将多维关联数组展平为PHP中的一个一维引用数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆