You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于$filterContains与$filterExclude的产品数组过滤功能异常排查

数据结构说明

$data->products 是包含约10000个产品的数组,每个产品均带有参数,结构如下:

Array
(
    [0] => Array
        (
            [id] => 440
            [name] => Product1
            [parameters] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => Parameter1
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 1
                                            [name] => ValueParameter1
                                        )

                                )

                        )
                    [1] => Array
                        (
                            [id] => 2
                            [name] => Parameter2
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 2
                                            [name] => ValueParameter2
                                        )

                                )

                        )
                    [2] => Array
                        (
                            [id] => 3
                            [name] => Parameter3
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 3
                                            [name] => ValueParameter3
                                        )

                                )

                        )
                    [3] => .........
                        ...
                )
        )

    [1] => Array
        (
            [id] => 14
            [name] => Product2
            [parameters] => Array
                (
                    [0] => Array
                        (
                            [id] => 2
                            [name] => Parameter2
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 2
                                            [name] => ValueParameter2
                                        )

                                )

                        )

                    [2] => Array
                        (
                            [id] => 3
                            [name] => Parameter3
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 3
                                            [name] => ValueParameter3
                                        )

                                )

                        )
                    [2] => Array
                        (
                            [id] => 35
                            [name] => Parameter35
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 64
                                            [name] => ValueParameter35
                                        )

                                )

                        )
                    [3] => .........
                        ...

                )

        )
    [2] => ....
    .....
需求说明
  • 需对$data->products数组进行过滤
  • $filterContains:参数ID数组,需保留包含该数组中所有参数ID的产品
  • $filterExclude:参数ID数组,需排除包含该数组中任意参数ID的产品
  • 最终需得到同时满足上述两个规则的产品数组
现有代码
function getFilteredData($data, array $filterContains = [], array $filterExclude = []): array
{
    $result = [];
    $keyCount = count($filterContains);
    foreach ($data->products as $product) {
        if (isset($product['parameters'])) {
            $match = 0;
            $product['parameters'] = array_values($product['parameters']);
            foreach ($product['parameters'] as $parameter) {
                foreach ($filterContains as $value) {
                    if ($parameter['id'] == $value && !in_array($parameter['id'], $filterExclude)) {
                        $match++;
                    }
                }
                if ($match == $keyCount) {
                    $result[] = $product;
                }
            }
        }
    }
    $unique_array = [];
    foreach ($result as $element) {
        $hash = $element['id'];
        $unique_array[$hash] = $element;
    }
    $result = array_values($unique_array);
    return $result;
}
问题排查与修复

问题根源

现有代码存在两个核心问题:

  1. 仅在匹配$filterContains的参数时才检查是否属于$filterExclude,完全忽略了产品中存在排除列表内其他参数的情况——只要产品包含任意一个排除参数,就应直接被排除,无论是否满足包含条件。
  2. 匹配逻辑有漏洞:若产品参数中重复出现同一个包含列表内的ID,会导致$match错误累加,可能误判为满足全包含要求。

修复后的代码

function getFilteredData($data, array $filterContains = [], array $filterExclude = []): array
{
    $result = [];
    foreach ($data->products as $product) {
        if (!isset($product['parameters'])) {
            // 无参数产品:仅当两个过滤列表都为空时保留
            if (empty($filterContains) && empty($filterExclude)) {
                $result[] = $product;
            }
            continue;
        }

        // 提取当前产品的所有参数ID并去重
        $productParamIds = array_unique(array_column($product['parameters'], 'id'));

        // 优先检查排除规则:只要有一个参数在排除列表中,直接跳过
        if (!empty($filterExclude) && array_intersect($productParamIds, $filterExclude)) {
            continue;
        }

        // 检查包含规则
        if (empty($filterContains)) {
            // 包含列表为空,且已通过排除检查,加入结果
            $result[] = $product;
        } else {
            // 计算产品参数与包含列表的交集,长度匹配则说明全包含
            $matched = array_intersect($productParamIds, $filterContains);
            if (count($matched) === count($filterContains)) {
                $result[] = $product;
            }
        }
    }

    // 按产品ID去重
    $uniqueResult = [];
    foreach ($result as $item) {
        $uniqueResult[$item['id']] = $item;
    }
    return array_values($uniqueResult);
}

修复说明

  1. 优先处理排除规则:先提取产品所有参数ID,只要和排除列表有交集就直接跳过,逻辑更高效清晰。
  2. 准确匹配包含规则:用array_intersect计算交集,通过交集长度判断是否包含所有要求的参数,避免重复计数问题。
  3. 兼容边界场景:处理无参数产品、过滤列表为空的情况,保证逻辑完整性。
  4. 性能优化:用array_column和array_unique替代多层循环,更适合处理10000条级别的数据。

内容的提问来源于stack exchange,提问作者nxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:16:04