在 PHP 中展平 JSON 多级数组

Posted

技术标签:

【中文标题】在 PHP 中展平 JSON 多级数组【英文标题】:Flattening a JSON multi depty array in PHP 【发布时间】:2015-04-08 05:43:49 【问题描述】:

早上好,给定以下数据结构(为便于阅读,采用 JSON 格式)

[

    "parent": "root",
    "active": "1",
    "label": "Index",
    "route": "/",
    "children": [
        
            "parent": "/",
            "active": "1",
            "label": "Products",
            "route": "/products",
            "children": [
                
                    "parent": "/products",
                    "active": "0",
                    "label": "Test",
                    "route": "/test"
                
            ]
        
    ]
    ,
    
        "parent": "root",
        "active": "1",
        "label": "404",
        "route": "/404"
    ,
    
        "parent": "root",
        "active": "1",
        "label": "Login",
        "route": "/login"
    
]

我在从函数返回以下结构时遇到了很大的问题:

[

    "parent": "root",
    "active": "1",
    "label": "Index",
    "route": "/"
,

    "parent": "/products",
    "active": "0",
    "label": "Test",
    "route": "/test"
,

    "parent": "/",
    "active": "1",
    "label": "Products",
    "route": "/products"
,

    "parent": "root",
    "active": "1",
    "label": "404",
    "route": "/404"
,

    "parent": "root",
    "active": "1",
    "label": "Login",
    "route": "/login"

]

本质上,我想通过所有子级递归并用嵌套数组中的每个父级和子级填充一个新数组,我尝试了 array_merge、RecursiveIteratorIterator、itterator_to_array、array_map,但它总是在递归上卡住。当孩子们只有一层深度但两层或更多层根本崩溃时,我设法做到了。

请帮忙!

【问题讨论】:

你试过***.com/a/1320259/2529486 VeeeneX : 是的,他们没有给我想要的结果,他们只返回父母而不是孩子。 【参考方案1】:

简单易懂

function flatten($items, &$r) 
    foreach($items as $item) 
        $c = isset($item->children) ? $item->children : null;
        unset($item->children);
        $r []= $item;
        if($c)
            flatten($c, $r);
    


flatten(json_decode($json), $r);
print_r($r);

这会将结果累积到一个缓冲区中,通过引用传递。这比在每次迭代中构建一个全新的数组要高效得多,后者基本上是Shlemiel the painter's algorithm 的变体。

如果您更喜欢函数式方法,可以使用generators:

function flatten($items) 
    foreach($items as $item) 
        $c = isset($item->children) ? $item->children : [];
        unset($item->children);
        yield $item;
        foreach(flatten($c) as $child)
            yield $child;
    


foreach(flatten(json_decode($json)) as $item)
    print_r($item);

【讨论】:

我当然同意我的算法更加“浪费”。我只是更喜欢函数式方法和符号,而不是通过引用传递结果作为参数。对我来说,以你的方式重写它必须是一个已证明的瓶颈。 +1 :) 这些函数容易可逆吗?例如,将这些输出结构转换回我原来的 json? @user3169851:是的,遍历平面结果并将当前项目添加到$tree[$item->parent]->children【参考方案2】:

不是很难:

function flatten(array $array) 
    $branch = [];

    foreach ($array as $item) 
        $children = [];
        if (isset($item['children']) && is_array($item['children'])) 
            $children = flatten($item['children']);
            unset($item['children']);
        
        $branch = array_merge($branch, [$item], $children);
    

    return $branch;

【讨论】:

以上是关于在 PHP 中展平 JSON 多级数组的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 pyspark 在 aws 胶水中展平嵌套 json 中的数组?

雪花中具有多个 JSON 对象的横向展平数组

使用 Jq 展平 JSON,并在输出中使用数组索引

如何展平多级/嵌套 JSON?

如何在 PHP 中展平数组?

使用 jq 为 JSON 对象的嵌套数组中的属性展平数组