F# 如何优雅实现浮点数数组逆向扫描替换前置NaN值
最优简洁实现
利用F#内置Array.scanBack原生的逆序遍历特性,完全匹配需求的扫描方向,无需手动反转数组、拼接冗余元素,代码量远低于现有实现:
let fillNaNs (arr: float[]) = arr |> Array.scanBack (fun x lastValid -> if Double.IsNaN x then lastValid else x) arr[^0] |> Array.take arr.Length
实现逻辑
Array.scanBack默认从数组末尾向头部遍历,每一步接收两个参数:当前遍历到的元素、上一步计算得到的最近非NaN值,输出当前位置对应的新的最近非NaN值- 初始的最近非NaN值直接取数组最后一个元素
arr[^0],题目明确该值确定不是NaN,无需额外校验 Array.scanBack的返回结果会比原数组长1个元素(末尾附带初始状态值),通过Array.take切掉多余的末尾元素,得到的就是符合要求的最终数组
验证效果
对示例输入[| 1.; 2.; nan; 4.; 5. |],执行上述实现的输出为[| 1.; 2.; 4.; 4.; 5. |],和预期完全一致。
对于多连续NaN的边界场景(比如输入[| nan; nan; 3. |]),输出也会正确填充为[| 3.; 3.; 3. |]。
相比原有实现的优势
- 全流程单次遍历数组,时间复杂度O(n),没有多次反转、重复拼接数组带来的额外内存拷贝开销
- 完全由F#核心库的内置函数组合实现,没有手写循环,贴合函数式编程的风格
- 没有冗余的状态存储,代码逻辑直观
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

