如何过滤层级组合数组,移除被其他条目完全包含的子集条目
如何过滤层级组合数组,移除被其他条目完全包含的子集条目
嘿,我来帮你搞定这个层级数组过滤的问题!先把需求掰扯清楚:你手里有一组公司层级的组合数组,每个条目是关联数组,层级顺序是division > department > team,有些层级可能是null。现在要剔除那些被其他条目完全覆盖的子集条目,只保留最具体的、没有更细化对应条目的组合——说白了就是,如果某个条目存在一个更具体的“子条目”(包含它的所有非null层级,还多了其他具体层级),那这个父条目就该被删掉。
比如你给的示例里:
["division" => "division1"]被后面的division1+department10+team85、division1+null+team91这些更具体的条目覆盖了,所以要移除;["division" => "division1", "department" => "department10"]被division1+department10+team85覆盖,也得删掉;- 而
division1+null+team91、division1+null+team92这些没有更具体的条目对应,就保留下来。
接下来给你一个可行的实现思路和代码示例(用PHP写的,因为你的示例是PHP风格的数组):
实现思路
- 先明确层级的优先级顺序:
division>department>team,这是判断子集的基础; - 写一个辅助函数,用来判断条目A是否是条目B的子集:
- 检查A的所有非null层级,是否和B的对应层级值完全一致;
- 同时B必须比A更具体——也就是B至少有一个层级是有值(非null),而A的对应层级是
null或者不存在;
- 遍历原数组,对每个条目,检查是否存在其他条目让它成为子集,如果存在就丢弃,否则保留。
代码实现
// 定义层级顺序,按从高到低排列 $hierarchyOrder = ['division', 'department', 'team']; /** * 判断条目$a是否是条目$b的子集(即$b比$a更具体,且覆盖$a的所有非null层级) */ function isSubset(array $a, array $b, array $hierarchy) { // 第一步:检查$a的所有非null层级是否都和$b的对应值一致 foreach ($hierarchy as $level) { $aVal = $a[$level] ?? null; $bVal = $b[$level] ?? null; if ($aVal !== null && $aVal !== $bVal) { return false; } } // 第二步:检查$b是否比$a更具体(至少有一个层级$a是null,$b有值) $hasMoreSpecific = false; foreach ($hierarchy as $level) { $aVal = $a[$level] ?? null; $bVal = $b[$level] ?? null; if ($aVal === null && $bVal !== null) { $hasMoreSpecific = true; break; } } return $hasMoreSpecific; } // 你的原始数组 $originalArray = [ ["division" => "division1"], ["division" => "division2"], ["division" => "division1", "department" => "department10"], ["division" => "division1", "department" => null, "team" => "team91"], ["division" => "division1", "department" => "department10", "team" => "team85"], ["division" => "division3", "department" => "department999"], ["division" => "division2", "department" => "department33"], ["division" => "division1", "department" => null, "team" => "team92"], ]; // 过滤数组 $filteredArray = []; foreach ($originalArray as $currentItem) { $shouldKeep = true; foreach ($originalArray as $otherItem) { // 跳过自身比较 if ($currentItem === $otherItem) { continue; } // 如果当前条目是另一个条目的子集,标记为不保留 if (isSubset($currentItem, $otherItem, $hierarchyOrder)) { $shouldKeep = false; break; } } if ($shouldKeep) { $filteredArray[] = $currentItem; } } // 输出结果 print_r($filteredArray);
运行这段代码后,得到的结果就是你期望的数组:
Array ( [0] => Array ( [division] => division1 [department] => [team] => team91 ) [1] => Array ( [division] => division1 [department] => [team] => team92 ) [2] => Array ( [division] => division1 [department] => department10 [team] => team85 ) [3] => Array ( [division] => division3 [department] => department999 ) [4] => Array ( [division] => division2 [department] => department33 ) )
小优化提示
如果你的数组很大,上面的双重循环效率可能不高。可以先把数组按“非null层级的数量”从多到少排序,这样在检查的时候,一旦找到一个更具体的条目,就可以直接终止检查,能节省不少时间~
备注:内容来源于stack exchange,提问作者pileup
相关产品推荐
相关产品推荐

