我想遍历一个像[:foo, :bar, :baz]
这样的数组。
在每次迭代中,我想要项目和下一个项目。在最后一次迭代中,"下一项"应该是nil
所以我想依次生成:foo, :bar
,然后是:bar, :baz
,最后是:baz, nil
。
我可以想到一些实现这一目标的方法:
my_list.zip(my_list.from(1)) { |item, next_item| … }
my_list.each.with_index(1) { |item, i| next_item = my_list[i] }
[*my_list, nil].each_cons(2) { |item, next_item| … }
但我觉得我可能错过了一些更简单的方法。我是吗?
如果你的Array中只有三个非nil元素,并且每次都想从#each_cons中获取两个元素,那么只需添加一个nil,然后就可以结束了。
%i[foo bar baz].push(nil).each_cons(2).map { [_1, _2] }
#=> [[:foo, :bar], [:bar, :baz], [:baz, nil]]
或者,您可以根据当前或后续索引号引用命名数组的每个索引元素,因为对数组边界之外的元素的任何引用都将为nil。例如:
array = %i[foo bar baz]
array.each_index.map { [array[_1], array[_1.succ]] }
#=> [[:foo, :bar], [:bar, :baz], [:baz, nil]]
无论哪种情况,如果你想返回数组对象的数组,你都需要#map或其他机制。如果你想做其他事情,比如yield,你也可以这样做。
注意,如果要使用可变数量的Array元素,或者更改#each_cons项的数量,则需要使用不同的方法。如果是这种情况,请随意打开一个新的或相关的问题。