
在构建和管理内容系统时,我们经常会遇到层级分类树的场景。例如,一个网站可能包含多个主类别,每个主类别下又包含子类别,直至最细粒度的分类。每个类别节点可能直接关联着具体的内容,也可能仅仅作为其子类别的容器。然而,随着内容的增删,一些类别节点可能会变得“空”——即它们本身没有关联任何内容,并且其所有子类别也都没有关联任何内容。为了保持分类树的整洁和有效性,我们需要一种机制来自动移除这些“空”类别,确保分类树中的每个路径最终都能导向一个包含内容的类别。
假设我们拥有以下结构的分类数据:
[uid_of_category]
=> (array)content // 关联内容,可能为空
=> (array)sub_categories // 子类别数组,可能为空
=> [uid_of_category]
=> (array)content
=> (array)sub_categories
...我们的目标是:仅保留那些直接包含内容,或者其子类别(无论层级多深)中包含内容的类别节点。
处理树形结构数据,递归是一种非常高效且自然的解决方案。为了清晰地分离判断逻辑和执行逻辑,我们采用双函数递归策略:
isCleanable 函数的核心逻辑是自底向上地判断。如果一个类别:
/**
* 判断一个类别是否可以被清理(即其自身及所有子孙节点都无内容)
*
* @param array $category 待判断的类别节点
* @return bool 如果类别及其所有子孙节点都无内容,则返回 true;否则返回 false。
*/
function isCleanable(array $category): bool
{
// 1. 如果当前类别直接包含内容,则它不可被清理
if (!empty($category['content'])) {
return false;
}
// 2. 如果当前类别没有直接内容,则检查其子类别
// 遍历所有子类别,只要有一个子类别不可被清理(即其包含内容),
// 那么当前类别也就不应被清理。
foreach ($category['sub_categories'] as $subCategory) {
if (!isCleanable($subCategory)) {
return false; // 子类别有内容,则当前类别不可清理
}
}
// 3. 如果当前类别无内容,且所有子类别都可被清理(即子类别也无内容),
// 那么当前类别就是可清理的。
return true;
}cleanCategories 函数负责遍历类别数组,并利用 isCleanable 的结果来决定是否移除某个类别。需要注意的是,为了能够修改原始数组,该函数必须接收类别数组的引用 (&) 作为参数。
/**
* 递归清理类别数组,移除所有可清理的空类别。
*
* @param array &$categories 类别数组的引用,将被修改。
*/
function cleanCategories(array &$categories): void
{
foreach ($categories as $key => &$category) { // 注意这里 $category 也是引用,但实际修改的是 $categories[$key]
if (isCleanable($category)) {
unset($categories[$key]); // 移除可清理的类别
} else {
// 如果当前类别不可清理(因为它有内容或其子类别有内容),
// 则继续递归清理其子类别。
cleanCategories($category['sub_categories']);
}
}
}假设我们有如下的初始分类数据:
$categoryTree = [
'cat1' => [
'content' => [], // 空内容
'sub_categories' => [
'cat1_1' => [
'content' => ['item_a'], // 有内容
'sub_categories' => []
],
'cat1_2' => [
'content' => [], // 空内容
'sub_categories' => [
'cat1_2_1' => [
'content' => ['item_b'], // 有内容
'sub_categories' => []
],
'cat1_2_2' => [
'content' => [], // 空内容
'sub_categories' => []
]
]
],
'cat1_3' => [
'content' => [], // 空内容
'sub_categories' => []
]
]
],
'cat2' => [
'content' => [], // 空内容
'sub_categories' => [
'cat2_1' => [
'content' => [], // 空内容
'sub_categories' => [
'cat2_1_1' => [
'content' => [], // 空内容
'sub_categories' => []
]
]
]
]
],
'cat3' => [
'content' => ['item_c'], // 有内容
'sub_categories' => []
]
];
// 执行清理操作
cleanCategories($categoryTree);
// 打印清理后的结果
print_r($categoryTree);预期清理结果分析:
最终的 $categoryTree 将只包含 cat1 (及其内部有效的子树) 和 cat3。
通过 isCleanable 和 cleanCategories 这两个递归函数的协同工作,我们能够优雅且高效地清理复杂的嵌套类别树。这种双函数策略分离了判断逻辑和执行逻辑,使得代码更加模块化和易于维护。理解递归在处理树形结构中的应用,是解决此类问题的关键。
以上就是清理嵌套分类树中的空类别的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号