Ruby遍历元素及下一项(末位下一项为nil)的最简实现方法
实现数组遍历同时取当前元素与下一个元素(末尾补nil)
需求说明
遍历形如[:foo, :bar, :baz]的数组时,每次迭代同时获取当前元素及其对应的下一个元素,最后一次迭代时「下一个元素」取值为nil,迭代过程依次产出三组配对值:
:foo, :bar:bar, :baz:baz, nil
已有的三种可行实现
目前已验证可满足需求的写法共三种:
- 依赖ActiveSupport扩展的zip写法:
my_list.zip(my_list.from(1)) { |item, next_item| … } - 带索引遍历写法:
my_list.each.with_index(1) { |item, i| next_item = my_list[i] } - 追加nil后用each_cons写法:
[*my_list, nil].each_cons(2) { |item, next_item| … }
更简洁的原生Ruby实现
最简洁的无依赖原生写法是优化后的zip方案:
my_list.zip(my_list[1..]) { |item, next_item| # 写入你的处理逻辑 }
这个写法利用了Ruby原生Array#zip的内置特性:返回结果长度和调用zip的原数组长度一致,当传入的参数数组长度不足时,对应位置会自动填充nil,不需要手动给数组追加nil,也不需要额外做索引取值赋值。
如果是2.6以下不支持无上限范围语法的Ruby版本,把my_list[1..]换成my_list[1..-1]即可,效果完全一致。
不同写法的适用场景提示
- 原写法里的
my_list.from(1)是Rails ActiveSupport的扩展方法,纯Ruby环境下会报错,替换成my_list[1..]就可以全环境兼容。 - 带索引遍历的写法性能最好,不会创建额外的中间数组,处理百万级以上的超大数组时可以优先选择。
[*my_list, nil].each_cons(2)的可读性很强,日常业务代码使用完全没问题,仅会额外生成一个长度+1的新数组,内存开销几乎可以忽略。
内容的提问来源于stack exchange,提问作者Henrik N
相关产品推荐
相关产品推荐

