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

PHP/JS实现价格数组中异常不均匀价格的过滤移除方法

邻域基准法过滤价格异常值方案

问题说明

待处理的价格数组示例如下:

$arr = [200,201,203,205,207,300,209,212,0,211,0,0,301,213,214];

数组中存在0、300、301这类不符合连续波动规律的异常值,已知正常价格区间为200-400,待处理数组长度通常在1000以上,要求仅基于邻域数据完成异常判断。

原有方案问题

最初采用相邻值差值阈值的过滤逻辑:

$fresharray = [];
$i = 0;
foreach($arr as $lol)
{
    $diff =  $lol - $arr[$i-1];
    if($diff < -50 || $diff > 50)
    { 
        // 差值超过阈值则判定为异常,跳过
    }
    else 
    {
        $fresharray[] = $lol;
    }
    $i++;
}

该方案存在两个核心问题:

  • 未初始化$i变量,首次循环会取数组最后一个元素做对比,初始判断逻辑完全失效
  • 仅以紧邻的上一个值为判断基准,遇到连续异常值场景(如连续两个0、连续的300和301)时,异常值之间差值仅为0或1,会被误判为正常值加入结果集

优化逻辑

核心是避免单值作为判断基准,采用固定长度的最近正常值队列作为判断基准池,彻底规避连续异常值的干扰:

  • 先做区间粗筛,直接排除不在200-400正常区间内的明显异常值
  • 维护长度为3的最近正常价格队列,取队列平均值作为当前值的对比基准
  • 当前值与基准值差值不超过阈值(默认50)则判定为正常值,加入结果集同时更新基准池
  • 差值超阈值则判定为异常跳过,基准池不做更新,避免异常值污染基准
  • 全程仅需一次遍历,时间复杂度O(n),可轻松适配万级长度数组

代码实现

PHP版本

/**
 * 过滤价格数组中的异常值
 * @param array $priceArr 原始价格数组
 * @param int $threshold 邻域差值阈值,默认50
 * @param int $minNormal 正常价格最小值,默认200
 * @param int $maxNormal 正常价格最大值,默认400
 * @param int $baseWindowSize 基准窗口大小,默认3
 * @return array 过滤后的正常价格数组
 */
function filterAbnormalPrice(array $priceArr, int $threshold = 50, int $minNormal = 200, int $maxNormal = 400, int $baseWindowSize = 3): array
{
    $result = [];
    $normalBase = []; // 存储最近确认的正常价格作为基准

    foreach ($priceArr as $price) {
        // 第一步:区间粗筛,直接排除明显超出正常范围的值
        if ($price < $minNormal || $price > $maxNormal) {
            continue;
        }

        // 初始阶段基准池未填满时,直接将符合区间的值作为初始基准
        if (count($normalBase) < $baseWindowSize) {
            $result[] = $price;
            $normalBase[] = $price;
            continue;
        }

        // 计算基准池平均值作为对比基准
        $baseAvg = array_sum($normalBase) / count($normalBase);
        if (abs($price - $baseAvg) <= $threshold) {
            $result[] = $price;
            // 更新基准池:移除最早的基准值,加入新的正常值
            array_shift($normalBase);
            $normalBase[] = $price;
        }
    }

    return $result;
}

// 测试示例
$arr = [200,201,203,205,207,300,209,212,0,211,0,0,301,213,214];
print_r(filterAbnormalPrice($arr));
// 输出结果:Array ( [0] => 200 [1] => 201 [2] => 203 [3] => 205 [4] => 207 [5] => 209 [6] => 212 [7] => 211 [8] => 213 [9] => 214 )

JavaScript版本

/**
 * 过滤价格数组中的异常值
 * @param {number[]} priceArr 原始价格数组
 * @param {number} threshold 邻域差值阈值,默认50
 * @param {number} minNormal 正常价格最小值,默认200
 * @param {number} maxNormal 正常价格最大值,默认400
 * @param {number} baseWindowSize 基准窗口大小,默认3
 * @returns {number[]} 过滤后的正常价格数组
 */
function filterAbnormalPrice(priceArr, threshold = 50, minNormal = 200, maxNormal = 400, baseWindowSize = 3) {
    const result = [];
    const normalBase = [];

    for (const price of priceArr) {
        // 区间粗筛
        if (price < minNormal || price > maxNormal) {
            continue;
        }

        // 初始基准池填充
        if (normalBase.length < baseWindowSize) {
            result.push(price);
            normalBase.push(price);
            continue;
        }

        // 计算基准平均值
        const baseAvg = normalBase.reduce((sum, val) => sum + val, 0) / normalBase.length;
        if (Math.abs(price - baseAvg) <= threshold) {
            result.push(price);
            normalBase.shift();
            normalBase.push(price);
        }
    }

    return result;
}

// 测试示例
const arr = [200,201,203,205,207,300,209,212,0,211,0,0,301,213,214];
console.log(filterAbnormalPrice(arr));
// 输出结果:[200, 201, 203, 205, 207, 209, 212, 211, 213, 214]

可调参数说明:如果价格波动幅度更大,可以适当调大threshold阈值;如果异常值比例更高,可以适当增大baseWindowSize窗口大小,也可以将基准平均值替换为中位数,进一步提升抗干扰能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:03:20