如何将嵌套数组各层级提取为带指定键值对的独立数组?
问题描述
我有一个4级嵌套数组,每一层代表组织中的一个层级。每一层的键为层级值,内部包含该层级在数组中的id。最后一层仅为值-id对:
$data = [ "top_level_data1" => [ 'top_level_id' => 0, 'sub_level_1' => [ 'sub_level_1_id' => 0, 'sub_level_2_data1' => [ 'sub_level_2_id' => 0, 'sub_level_2_data' => [ 0 => "some_val", 1 => "some_other_val" ] ] ] ], "top_level_data2" => [ 'level_1_id' => 1, 'sub_level_1_other' => [ 'sub_level_1_id' => 1, 'sub_level_2_data2' => [ 'sub_level_2_id' => 1, 'sub_level_3_data1' => [ 2 => "another_val", 3 => "bar", 4 => "foo" ] ], 'sub_level_2_data3' => [ 'sub_level_2_id' => 2, 'sub_level_3_data2' => [ 5 => "foobar", 6 => "hello", 7 => "goodbye" ] ] ] ] ];
我希望将其提取为包含层级值-id对的独立数组。上述示例的预期输出(不含上层id):
$top_level = [ 0 => "top_level_data1", 1 => "top_level_data2" ]; $sub_level_1 = [ 0 => "sub_level_1", 1 => "sub_level_1_other" ]; $sub_level_2 = [ 0 => "sub_level_2_data1", 1 => "sub_level_2_data2", 2 => "sub_level_2_data3" ]; $sub_level_3 = [ 0 => "some_val", 1 => "some_other_val", 2 => "another_val", 3 => "bar", 4 => "foo", 5 => "foobar", 6 => "hello", 7 => "goodbye" ];
我尝试使用RecursiveIterator但未能成功(起初只想用它验证迭代是否正确,还未按需求分配键值,但结果不符合预期):
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($data)); foreach($it as $key => $val) { $level[$it->getDepth()][] = $val; }
解决方案
可以通过嵌套循环逐层遍历数组,根据层级的id键特征分类收集数据,代码如下:
<?php $data = [ "top_level_data1" => [ 'top_level_id' => 0, 'sub_level_1' => [ 'sub_level_1_id' => 0, 'sub_level_2_data1' => [ 'sub_level_2_id' => 0, 'sub_level_2_data' => [ 0 => "some_val", 1 => "some_other_val" ] ] ] ], "top_level_data2" => [ 'level_1_id' => 1, 'sub_level_1_other' => [ 'sub_level_1_id' => 1, 'sub_level_2_data2' => [ 'sub_level_2_id' => 1, 'sub_level_3_data1' => [ 2 => "another_val", 3 => "bar", 4 => "foo" ] ], 'sub_level_2_data3' => [ 'sub_level_2_id' => 2, 'sub_level_3_data2' => [ 5 => "foobar", 6 => "hello", 7 => "goodbye" ] ] ] ] ]; // 初始化各层级结果数组 $top_level = []; $sub_level_1 = []; $sub_level_2 = []; $sub_level_3 = []; // 遍历顶层数据 foreach ($data as $name => $top_item) { // 提取顶层id,兼容不同键名 $id = $top_item['top_level_id'] ?? $top_item['level_1_id']; $top_level[$id] = $name; // 遍历一级子层 foreach ($top_item as $sub1_name => $sub1_item) { // 跳过id键,只处理子层级数组 if (str_ends_with($sub1_name, '_id')) continue; $sub1_id = $sub1_item['sub_level_1_id']; $sub_level_1[$sub1_id] = $sub1_name; // 遍历二级子层 foreach ($sub1_item as $sub2_name => $sub2_item) { if (str_ends_with($sub2_name, '_id')) continue; $sub2_id = $sub2_item['sub_level_2_id']; $sub_level_2[$sub2_id] = $sub2_name; // 遍历三级子层(最后一层) foreach ($sub2_item as $sub3_key => $sub3_val) { if (str_ends_with($sub3_key, '_id')) continue; // 直接合并最后一层的键值对 $sub_level_3 = array_merge($sub_level_3, $sub3_val); } } } } // 输出验证结果 print_r($top_level); print_r($sub_level_1); print_r($sub_level_2); print_r($sub_level_3); ?>
逻辑说明
- 层级过滤:每一层遍历都跳过以
_id结尾的键,只处理包含子层级的数组项 - id兼容:针对顶层不同的id键名(
top_level_id/level_1_id)使用空合并运算符做兼容处理 - 最后一层处理:直接将最内层的键值对合并到结果数组,无需额外转换
内容的提问来源于stack exchange,提问作者pileup
相关产品推荐
相关产品推荐

