修改 2d 数组以在遇到特定键时创建嵌套数据集

Modify 2d array to create nested datasets when specific key is encountered

提问人:Alt C 提问时间:3/6/2023 最后编辑:mickmackusaAlt C 更新时间:3/7/2023 访问量:73

问:

我有一个这样的输入数组

$input = [
    ["relation" => "OR"],
    ["color" => 'green'],
    ["color" => 'yellow'],
    ["relation" => "AND"],
    ["color" => 'black'],
    ["color" => 'orange'],
    ["relation" => "OR"],
    ["color" => 'blue'],
    ["color" => 'violet'],
];

期望结果:

$output = array(
    'relation' => 'OR',
    array(
        "color" => 'green'
    ),
    array(
        "color" => 'yellow'
    ),
    array(
        "relation" => "AND",
        array(
            "color" => "black"
        ),
        array(
            "color" => "orange"
        ),
        array(
            "relation" => "OR",
            array(
                "color" => "blue"
            ),
            array(
                "color" => "violet"
            ),
        )
    )
);

我相信我需要做递归函数来处理这个问题。

我有这个,但只适用于一个级别

function generate_nested_array($array, $nested_tax_query = array(), $target_index = 0)
{

    //the first element is always the relation
    $nested_tax_query['relation'] = $array[0]['relation'];
    // unset the first element as it is not needed anymore
    unset($array[0]);


    $len = count($array);
    // reindex the array
    $array = array_values($array);


    foreach ($array as $element_key => $element) {
        if (isset($element['relation'])) {
            $target_index = $element_key;
            break;
        }
    }


    // put everything below the target index into the target index and leave the rest as it is
    for ($i = 0; $i < $len - 1; $i++) {
        if ($i < $target_index) {
            $nested_tax_query[] = $array[$i];
        } else {
            $nested_tax_query[$target_index][] = $array[$i];
        }
    }

    // last item in the nested array
    $len_nested  = count($nested_tax_query);

    // last item in the in the nested array
    $last_item_in_nested_array  = $nested_tax_query[$len_nested - 2]; 


    return $nested_tax_query;
}

我的方法正确吗?

PHP 多维数组 数据结构 嵌套

评论

1赞 Gus Hogg-Blake 3/6/2023
固定格式 - 您可以使用三反引号来标记多行代码块。

答:

-1赞 Gus Hogg-Blake 3/6/2023 #1

你是对的,递归将是一个很好的方法。首先,我建议按原样保留原始数组,这样您就不必考虑它在处理它时会经历的各种修改。要将其部分标记为已处理,可以使用索引(如参数所建议的那样)或将数组的切片传递给递归调用。target_index

我认为你已经接近了,你只需要在函数结束时对数组的其余部分(如果有更多的元素要处理)做一些事情。

评论

1赞 mickmackusa 3/7/2023
我看到了提示和鼓励,但没有实际解决所提出的问题的解决方案。这可能是一个好答案的开始。
3赞 mickmackusa 3/7/2023 #2

我没有看到使用递归的意义。我发现参考变量是一种更直观的方法。每次遇到新的 时,将“引用”更改为引用所在的新/最后一个元素。relation

不处理数据时,您可以安全地将数据直接推送到当前引用变量中,它将完全位于您希望的位置。relation

代码:(演示)

$ref = [];
$result = &$ref;
foreach ($input as $row) {
    if  (key($row) !== 'relation') { // populate current level
        $ref[] = $row; // push color into reference
        continue;
    }
    if ($ref) {  // not the first relation encountered
        $ref = &$ref[];  // set $ref to point to new deeper subarray
    }
    $ref = $row; // push relation
}

var_export($result);

或者以不同的方向使用相同的逻辑:(演示)

$ref = [];
$result = &$ref;
foreach ($input as $row) {
    if (key($row) === 'relation') {
        if ($ref) {  // not the first relation encountered
            $ref = &$ref[];  // set $ref to point to new deeper subarray
        }
        $ref = $row; // push relation
    } else {
        $ref[] = $row; // push color into reference
    }
}

var_export($result);

评论

1赞 Alive to die - Anant 3/7/2023
这太棒了。如此简单而优雅。我也试着去做,但没能做到(虽然我没有太多时间去做)+1。
1赞 Alt C 3/7/2023
天哪!简直不敢相信,几行代码就能搞定 非常感谢!
0赞 mickmackusa 3/7/2023
老实说,我对这个感到惊讶。我的第一个工作脚本更加冗长/笨拙。在得出此解决方案之前,我编辑/改进了该片段大约 8 或 10 次。这是一项有趣的任务。我会收藏这个页面。