在PHP中动态创建/插入关联数组

5

我正在尝试动态地在PHP中构建关联数组,但我的策略还不太正确。基本上,我想在数组结构的某个深度处插入一个值,例如:

$array['first']['second']['third'] = $val;

现在的问题是,我不确定是否有这个深度可用,如果没有,我想为每个级别创建键(和数组),最后将值插入到正确的级别。

由于我在代码中经常这样做,我厌倦了做大量的“array_key_exists”,因此我想编写一个函数,根据级别键列表为我构建数组。任何关于这个的好策略的帮助都将不胜感激。我相信有一种非常简单的方法,只是我还没想到...


你能展示一下你开始使用的数据集的例子吗?当你说“level keys”等时。顺便说一句,欢迎来到SO :-) - richsage
你的数据插入格式是怎样的?比如键和$val存储在什么结构中? - Andy
@richsage:谢谢!@richsage和@Andy: 我将尝试使用示例结构更新帖子。基本上,我正在尝试创建一个结构来保存一个半复杂的表单,包括顶部的部分、字段集、行ID、行标签文本和行值。 - Emil
4个回答

9

PHP并不会责怪你,即使你只是这样做。

$array['first']['second']['third'] = $val;
print_r($array);

如果您不想将密钥硬编码,这里有一个灵活的解决方案。
/// locate or create element by $path and set its value to $value
/// $path is either an array of keys, or a delimited string
function array_set(&$a, $path, $value) {
    if(!is_array($path))
        $path = explode($path[0], substr($path, 1));
    $key = array_pop($path);
    foreach($path as $k) {
        if(!isset($a[$k]))
            $a[$k] = array();
        $a = &$a[$k];
    }
    $a[$key ? $key : count($a)] = $value;
}

// example:
$x = array();

array_set($x, "/foo/bar/baz", 123);
array_set($x, "/foo/bar/quux", 456);
array_set($x, array('foo', 'bah'), 789);

2
不会,但我认为使用未初始化的变量(如内部数组)是不好的编码风格。PHP会生成一个严格的NOTICE提示。 - soulmerge
@stereofrog:我认为“notice”是需要注意的事情,但是可以理解;“责备”可能有点过了。 - Decent Dabbler
@stereofrog - 非常感谢!这个方法十分有效。我之前也尝试过类似的方法,但一直无法理解其中的引用部分。现在我可以将余下的下午时间花在理解那部分内容上,而不是再拔下任何头发了。:-) - Emil
如果你知道数组键是正确的(可能不存在),并且要设置的值也是正确的,那么你可以使用错误控制运算符(@)来抑制该行的通知。 - Kenzal Hunter

4
创建一个函数,如下所示:
function insert_into(&$array, array $keys, $value) {
     $last = array_pop($keys);       

     foreach($keys as $key) {
          if(!array_key_exists($key, $array) || 
              array_key_exists($key, $array) && !is_array($array[$key])) {
                  $array[$key] = array();

          }
          $array = &$array[$key];
     }
     $array[$last] = $value;
}

使用方法:

$a = array();
insert_into($a, array('a', 'b', 'c'), 1);
print_r($a);

输出:

Array
(
    [a] => Array
        (
            [b] => Array
                (
                    [c] => 1
                )

        )

)

0
<?php

function setElements(&$a, array $path = [], $values = [])
{

    if (!is_array($path)) {
        $path = explode($path[0], substr($path, 1));
    }

        $path = "[ '" . join("' ][ '", $path) . "' ]";
        $code =<<<CODE
        if(!isset(\$a{$path})){
            \$a{$path} = [];
        }
        return \$a{$path}[]  = \$values;
CODE;

        return eval($code);
}

$a = [];
setElements($a, [1,2], 'xxx');
setElements($a, [1,2,3], 233);
setElements($a, [1,2,4], 'AAA');
setElements($a, [1,2,3,4], 555);
print_r($a);

输出

Array
(
    [1] => Array
        (
            [2] => Array
                (
                    [0] => xxx
                    [3] => Array
                        (
                            [0] => 233
                            [4] => Array
                                (
                                    [0] => 555
                                )

                        )

                    [4] => Array
                        (
                            [0] => AAA
                        )

                )

        )

)

你应该在这里检查 http://sandbox.onlinephpfunctions.com/


也许您可以解释一下这是做什么用的。提供代码示例很好,但是一些关于它意义的注释会更有帮助。 - byxor

0

这有点棘手,你需要使用引用(或递归,但我选择在这里使用引用):

# Provide as many arguments as you like:
# createNestedArray($array, 'key1', 'key2', etc.)
function createNestedArray(&$array) {
    $arrayCopy = &$array;
    $args = func_get_args();
    array_shift($args);
    while (($key = array_shift($args)) !== false) {
        $arrayCopy[$key] = array();
        $arrayCopy = &$arrayCopy[$key];
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接