在实际开发场景中,我们经常会遇到多层嵌套的数组结构,比如接口返回的树形数据、多级分类数据等,有时候需要把这些嵌套数组里某个指定键对应的所有值都提取出来,合并成一个没有层级的一维数组,方便后续做统计、筛选等操作。

通用实现思路
提取嵌套数组中指定键的值并扁平化,核心逻辑可以分为两个步骤:
- 遍历数组的每一个元素,判断当前元素是否为数组
- 如果当前元素是数组,先检查是否包含目标键,包含的话就把对应的值存入结果集,然后递归处理这个数组的子元素;如果不是数组就跳过当前元素
这个逻辑不管是哪种编程语言,只要支持数组遍历和递归,都可以按照这个思路实现。
PHP实现示例
PHP中可以用递归函数来实现这个功能,代码如下:
<?php
/**
* 提取嵌套数组中所有指定键的值并扁平化为一维数组
* @param array $data 待处理的嵌套数组
* @param string $targetKey 要提取的目标键名
* @return array 扁平化后的一维数组
*/
function extract_target_values(array $data, string $targetKey): array {
$result = [];
// 遍历当前层级的数组元素
foreach ($data as $item) {
// 如果当前元素是数组
if (is_array($item)) {
// 检查是否包含目标键
if (array_key_exists($targetKey, $item)) {
$result[] = $item[$targetKey];
}
// 递归处理子数组,合并结果
$result = array_merge($result, extract_target_values($item, $targetKey));
}
}
return $result;
}
// 测试数据
$testData = [
[
'id' => 1,
'name' => '分类1',
'children' => [
['id' => 2, 'name' => '分类1-1'],
['id' => 3, 'name' => '分类1-2']
]
],
[
'id' => 4,
'name' => '分类2',
'children' => [
['id' => 5, 'name' => '分类2-1']
]
]
];
// 提取所有name键的值
$names = extract_target_values($testData, 'name');
print_r($names);
// 输出结果:Array ( [0] => 分类1 [1] => 分类1-1 [2] => 分类1-2 [3] => 分类2 [4] => 分类2-1 )
?>
JavaScript实现示例
JavaScript的实现思路和PHP类似,同样使用递归处理,代码如下:
/**
* 提取嵌套数组中所有指定键的值并扁平化为一维数组
* @param {Array} data 待处理的嵌套数组
* @param {string} targetKey 要提取的目标键名
* @returns {Array} 扁平化后的一维数组
*/
function extractTargetValues(data, targetKey) {
let result = [];
// 遍历当前层级的数组元素
for (let item of data) {
// 如果当前元素是对象或者数组
if (typeof item === 'object' && item !== null) {
// 检查是否包含目标键
if (targetKey in item) {
result.push(item[targetKey]);
}
// 如果元素有children属性且是数组,递归处理
if (Array.isArray(item.children)) {
result = result.concat(extractTargetValues(item.children, targetKey));
} else {
// 遍历对象的所有属性,处理嵌套的对象值
for (let key in item) {
if (typeof item[key] === 'object' && item[key] !== null && Array.isArray(item[key])) {
result = result.concat(extractTargetValues(item[key], targetKey));
}
}
}
}
}
return result;
}
// 测试数据
const testData = [
{
id: 1,
name: '分类1',
children: [
{id: 2, name: '分类1-1'},
{id: 3, name: '分类1-2'}
]
},
{
id: 4,
name: '分类2',
children: [
{id: 5, name: '分类2-1'}
]
}
];
// 提取所有name键的值
const names = extractTargetValues(testData, 'name');
console.log(names);
// 输出结果:["分类1", "分类1-1", "分类1-2", "分类2", "分类2-1"]
注意事项
- 递归实现的时候要注意数组的层级深度,如果嵌套层级过深可能会导致栈溢出,这种情况下可以改用迭代的方式,用栈或者队列来保存待处理的元素
- 如果目标键对应的值本身也是数组,需要根据实际需求决定是否要把这个数组也扁平化,上面的示例默认只提取非数组的单个值,需要的话可以额外添加判断逻辑
- 处理数据之前最好先判断输入的数据类型是否符合要求,避免出现类型错误导致的异常
如果是比较简单的嵌套场景,也可以不用递归,用array_walk_recursive这类内置函数配合回调实现,不过递归方式的通用性更强,适配更多复杂的嵌套结构。