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

Swift:遍历数组并对比前后元素,如何用函数式方式实现?

Swift中用函数式风格实现相邻元素比较(以找局部最小值为例)

当然有函数式的实现方式啦!Swift标准库提供的序列操作工具完全能帮你摆脱那种带索引的while循环,写出更简洁、更符合函数式风格的代码——全程不需要可变变量,全靠纯函数来转换序列逻辑。

针对你找局部最小值的需求,核心思路是:把原数组拆分成三个对齐的序列——前一个元素序列、当前元素序列、后一个元素序列,然后通过zip把它们打包,就能同时拿到每个位置的前后元素进行比较了。

完整的函数式实现代码

let a = [1,2,2,3,5,4,2,5,7,9,5,3,8,10]
let localMinIndices = zip(1..<a.count-1, zip(zip(a.dropLast(2), a.dropFirst().dropLast()), a.dropFirst(2)))
    .filter { index, values in
        let (prev, curr) = values.0
        let next = values.1
        return curr < prev && curr < next
    }
    .map { $0.0 }

print(localMinIndices) // 输出 [6, 11]

代码逻辑拆解

  • a.dropLast(2):去掉数组最后两个元素,得到前n-2个元素,对应每个待检查元素的前一个元素;
  • a.dropFirst().dropLast():去掉第一个和最后一个元素,得到中间的n-2个元素,也就是我们要判断的当前元素;
  • a.dropFirst(2):去掉前两个元素,得到从第三个元素开始的n-2个元素,对应每个待检查元素的后一个元素;
  • zip(1..<a.count-1, ...):把索引范围(从1到数组长度-2,对应待检查元素的原始索引)和三组元素打包,这样每个元素都能关联上它的原始位置;
  • filter:筛选出当前元素同时小于前后元素的项;
  • map:提取出符合条件的索引。

简化版写法

如果觉得嵌套的zip看着有点绕,还可以调整解构方式让代码更清爽:

let localMinIndices = zip(1..<a.count-1, zip(a.dropLast(2), zip(a.dropFirst().dropLast(), a.dropFirst(2))))
    .filter { _, (prev, (curr, next)) in curr < prev && curr < next }
    .map(\.0)

要是你不需要索引,只需要局部最小值的元素本身,代码会更简单:

let localMins = zip(zip(a.dropLast(2), a.dropFirst().dropLast()), a.dropFirst(2))
    .filter { (prev, curr), next in curr < prev && curr < next }
    .map { $0.1 }

这种函数式写法的好处是逻辑更清晰,没有可变状态(比如原来的var i和var r),代码可读性和可维护性都更高~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:08:32