【问题标题】:PHP address array tree node using string or arrayPHP地址数组树节点使用字符串或数组
【发布时间】:2015-02-02 05:28:44
【问题描述】:

说,我有一个树结构中的数据,实现为任意深度的数组数组,类似于

print_r($my_array);

Array
(
    [id] => 123
    [value] => Hello, World!
    [child] => Array
        (
            [name] => Foo
            [bar] => baz
        )

    [otherchild] => Array
        (
            [status] => fubar
            [list] => Array
                (
                    [one] => 1
                    [two] => 3
                )

        )

    [sanity] => unchecked
)

现在,使用单个字符串作为键,我想在任意深度寻址一个节点,假设我有一个这样的键:

$key = 'otherchild|list|two';

使用这个键我希望能够处理存储在中的值

$my_array['otherchild']['list']['two']

显然,我可以explode('|', $key) 来获取一个键数组,然后将值从其中移出并使用它们来寻址子数组,这样就可以轻松获得我正在寻找的值,某事喜欢

$value = $my_array;
$keys = explode('|', $key);
while ($k = array_shift($keys)) {
    if (isset($value[$k])) {
        $value = $value[$k];
    } else {
        // handle failure
    }
} // Here, if all keys exist, $value holds value of addressed node

但我一直在尝试以通用方式更新值,即不必求助于类似

$keys = explode('|', $key);
if (count($keys) == 1) {
    $my_array[$keys[0]] = $new_value;
} else if (count($keys) == 2) {
    $my_array[$keys[0]][$keys[1]] = $new_value;
} else if ...

有什么想法吗?

【问题讨论】:

  • 您可以使用参考文献和与您在阅读时使用的方法类似的方法。当找不到节点时,只需创建它并继续。

标签: php arrays tree


【解决方案1】:
function setAt(array & $a, $key, $value)
{
    $keys = explode('|', $key);
    // Start with the root node (the array itself)
    $node = & $a;
    // Walk the tree, create nodes as needed
    foreach ($keys as $k) {
        // Create node if it does not exist
        if (! isset($node[$k])) {
             $node[$k] = array();
        }
        // Walk to the node
        $node = & $node[$k];
    }

    // Position found; store the value
    $node = $value;
}


// Test
$array = array();

// Add new values
setAt($array, 'some|key', 'value1');
setAt($array, 'some|otherkey', 'val2');
setAt($array, 'key3', 'value3');
print_r($array);
// Overwrite existing values
setAt($array, 'some|key', 'new-value');
print_r($array);

setAt($array, 'some', 'thing');
print_r($array);

【讨论】:

    【解决方案2】:

    如果您正在寻找简短的答案,也可以使用eval()

    $elem = "\$array['" . str_replace("|", "']['", $key) . "']";
    $val = eval("return isset($elem) ? $elem : null;");
    

    【讨论】:

    • 不要这样做。它很慢、很丑,而且如果$key 的值来自用户输入,那也是很危险的。
    • 明显慢?嗯,如果你在乎的话。丑陋的?代码并不总是漂亮的。危险的? PDO::query 和滥用一样危险,因为它可能导致 SQL 注入。作为开发者,你应该知道谨慎使用函数。
    • 我同意,但我还是不想使用eval() :-)
    猜你喜欢
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 2021-02-02
    相关资源
    最近更新 更多