
本文介绍一种高效算法,用于过滤多维数组中“被完全覆盖”的供应商行(即其所有 rolanid 均存在于其他某一行中),并自动精简每行的 rolanid 为相对于已保留行的差集,最终输出无冗余、语义清晰的结果。
本文介绍一种高效算法,用于过滤多维数组中“被完全覆盖”的供应商行(即其所有 rolanid 均存在于其他某一行中),并自动精简每行的 rolanid 为相对于已保留行的差集,最终输出无冗余、语义清晰的结果。
在处理供应商-商品 ID 映射类数据时,常需消除逻辑冗余:若某供应商(如 "ROLAN")的所有 rolanID 都已被另一个更全的供应商(如 "TEST DEPO")完全覆盖,则该行应被剔除;同时,保留行中若存在重叠 ID,也应只保留其独有部分,以确保每条记录语义独立、信息不重复。
核心思路分两步:
-
构建全局索引映射:遍历所有行,对每个
rolanID记录它出现过的所有行索引(如123 → [0, 1, 2]); -
识别“非子集”行:对每一行,计算其所有
rolanID对应的行索引交集 —— 若交集大小为1,说明该行的全部 ID 仅共同出现在它自己这一行,即它不是任何其他行的子集,应保留;否则(交集 ≥ 2),说明存在另一行包含它的全部 ID,应舍弃。
以下是完整可运行的 PHP 实现:
<?php
$test = [
[
"supplier" => "TEST DEPO",
"rolanID" => [123, 234, 456],
"itemCount" => 3
],
[
"supplier" => "ANOTHER DEPO",
"rolanID" => [123, 786, 345],
"itemCount" => 3
],
[
"supplier" => "ROLAN",
"rolanID" => [123, 234],
"itemCount" => 2
]
];
// Step 1: 构建 rolanID → [row_indices] 映射表
$idToRows = [];
foreach ($test as $idx => $row) {
foreach ($row['rolanID'] as $id) {
if (!isset($idToRows[$id])) {
$idToRows[$id] = [];
}
$idToRows[$id][] = $idx;
}
}
// Step 2: 筛选“非子集”行(即其 rolanID 不被任何其他单一行完全包含)
$keptIndices = [];
foreach ($test as $idx => $row) {
$commonRows = null;
foreach ($row['rolanID'] as $id) {
if (!isset($idToRows[$id])) continue;
if ($commonRows === null) {
$commonRows = $idToRows[$id];
} else {
$commonRows = array_intersect($commonRows, $idToRows[$id]);
}
}
// 若所有 rolanID 仅共同存在于当前行(交集大小为 1),则保留
if ($commonRows !== null && count($commonRows) === 1) {
$keptIndices[] = $idx;
}
}
// Step 3: 构建最终结果 —— 仅保留非子集行,并精简 rolanID 为相对差集
$result = [];
if (!empty($keptIndices)) {
// 第一个保留行原样加入
$firstIdx = $keptIndices[0];
$result[] = $test[$firstIdx];
// 后续保留行:计算其 rolanID 相对于所有已前置保留行的差集
for ($i = 1; $i < count($keptIndices); $i++) {
$currentIdx = $keptIndices[$i];
$currentIDs = $test[$currentIdx]['rolanID'];
$unionOfPrevIDs = [];
// 收集所有前置保留行的 rolanID 并去重合并
for ($j = 0; $j < $i; $j++) {
$prevIdx = $keptIndices[$j];
$unionOfPrevIDs = array_merge($unionOfPrevIDs, $test[$prevIdx]['rolanID']);
}
$unionOfPrevIDs = array_unique($unionOfPrevIDs);
// 取差集:仅保留当前行独有的 ID
$uniqueIDs = array_values(array_diff($currentIDs, $unionOfPrevIDs));
$result[] = [
'supplier' => $test[$currentIdx]['supplier'],
'rolanID' => $uniqueIDs,
'itemCount' => count($uniqueIDs)
];
}
}
print_r($result);✅ 输出结果:
Array
(
[0] => Array
(
[supplier] => TEST DEPO
[rolanID] => Array
(
[0] => 123
[1] => 234
[2] => 456
)
[itemCount] => 3
)
[1] => Array
(
[supplier] => ANOTHER DEPO
[rolanID] => Array
(
[0] => 786
[1] => 345
)
[itemCount] => 2
)
)⚠️ 注意事项:
- 该算法时间复杂度为 O(n × m)(n 为行数,m 为平均 rolanID 数),适用于中等规模数据;超大规模建议结合数据库
GROUP BY+NOT EXISTS优化; -
array_intersect要求输入为数组,空rolanID需提前校验,避免array_intersect([])返回空数组导致误判; - 若存在多个“最全行”(如两个供应商均含
{123,234,456,786}),算法会按原始顺序保留首个,后续同级行将因差集为空而被过滤 —— 这符合“最小冗余”设计目标; - 最终
itemCount动态反映精简后真实数量,确保业务逻辑一致性。
通过该方案,你不仅能准确识别并剔除被完全覆盖的冗余行,还能结构化地生成语义纯净、无交叉污染的数据集,显著提升后续统计、导出或 API 响应质量。

















