如何从波动型连续Decimal流中交替存储极值到数组?
解决交替峰值谷值捕捉问题
原代码的核心问题
你的伪代码逻辑存在一个关键缺陷:它在上升阶段会把每个比数组最后元素大的值都加入结果,下降阶段同理。这就导致你会把上升过程中的所有递增点都误判为“峰值”,而不是真正的趋势反转点——也就是上升转下降的那个最高点,或者下降转上升的那个最低点。比如你给的示例里,从0.3涨到1.3的过程中,原代码会把0.4、0.5…1.3全部塞进数组,完全不符合只抓极值的需求。
正确的思路:跟踪趋势反转
要准确捕捉交替的峰值和谷值,核心是跟踪当前的趋势方向(上升/下降),并在趋势发生反转时,记录反转前的那个极值。我们需要三个关键变量:
prevVal:存储上一个数据流的值,用来对比当前值判断趋势currentTrend:标记当前的趋势状态(初始态、上升、下降)extremes:存储最终峰值谷值的结果数组
优化后的伪代码实现
// 定义趋势状态枚举,清晰标记当前趋势 enum Trend { INITIAL, // 初始状态,还未确定趋势 UP, // 当前处于上升趋势 DOWN // 当前处于下降趋势 } var prevVal; var currentTrend = Trend.INITIAL; var extremes = []; void onEvent(Decimal val) { // 处理第一个值:直接作为第一个极值存入数组 if (prevVal == null) { extremes.push(val); prevVal = val; return; } // 判断当前值相对于上一个值的临时趋势 var tempTrend; if (val > prevVal) { tempTrend = Trend.UP; } else if (val < prevVal) { tempTrend = Trend.DOWN; } else { // 值相等时,不改变趋势,直接更新上一个值即可 prevVal = val; return; } // 根据当前趋势和临时趋势,判断是否发生反转 if (currentTrend == Trend.INITIAL) { // 第二个值,确定初始趋势方向 currentTrend = tempTrend; } else if (currentTrend != tempTrend) { // 趋势发生反转!记录上一个值作为极值 extremes.push(prevVal); // 更新当前趋势为新的方向 currentTrend = tempTrend; } // 更新上一个值为当前值,准备下一次对比 prevVal = val; }
验证示例数据流
用你给出的示例数据流走一遍逻辑,结果完全符合预期:
- 第一个值
0.3:存入extremes→[0.3],prevVal=0.3,趋势为INITIAL - 第二个值
0.4>0.3:临时趋势为UP,设置currentTrend=UP,prevVal=0.4 - 后续
0.5~1.2均大于前值,趋势无变化,仅更新prevVal - 遇到
1.2<1.3:临时趋势为DOWN,与当前UP趋势反转,存入prevVal=1.3→[0.3,1.3],趋势转为DOWN - 后续
1.1~0.1均小于前值,趋势无变化,仅更新prevVal - 遇到
0.1>0.0:临时趋势为UP,与当前DOWN趋势反转,存入prevVal=0.0→[0.3,1.3,0.0],趋势转为UP - 后续
0.2~1.0均大于前值,趋势无变化,仅更新prevVal - 遇到
1.0<1.1:临时趋势为DOWN,与当前UP趋势反转,存入prevVal=1.1→[0.3,1.3,0.0,1.1],完美匹配你的预期!
边界情况处理
- 连续相等值:比如数据流出现
0.5,0.5,0.5,代码会跳过记录,因为没有发生趋势变化,符合逻辑 - 初始趋势为下降:比如第一个值是
1.0,后续递减,代码会先存入1.0,当趋势反转上升时,记录谷值,同样符合交替极值的需求
内容的提问来源于stack exchange,提问作者boomboxboy
相关产品推荐
相关产品推荐

