假设我有一个@lines
的集合,我想迭代它,但我想根据集合的内容来操纵迭代的方式,我该怎么做?
即。像这样的东西:
@lines.each_with_index do |line, index|
if (index % 3 = 0)
jump_to index == next_multiple_of_3
end
end
所以看起来像这样:
Element | Index
a | 1
b | 2
c | 3
f | 6
g | 7
h | 8
i | 9
l | 12
我该怎么做?
修改1
请注意,正如我在下面的评论中所解释的那样,我并不总是希望跳到特定的倍数。基本上,我想跳转到一些任意索引,该索引由当前迭代中发生的事情决定。
首先,它可以向上跳转3
个索引,但是下次它会向上跳转7
个索引,然后在接下来的5个时间内跳转1
个正常,然后它会跳过2
个索引。
唯一不变的是确定它在原始迭代中如何进展的方式是基于当前迭代块内发生的事情。
答案 0 :(得分:6)
使用while循环并自行管理索引。我们不鼓励人们这么做多年。但这是一个合适的案例。 :)
idx = 0
while idx < @lines.length
line = @lines[idx]
idx += condition ? x : y # or whatever logic you have
end
当然,这假设@lines
能够随机访问。如果不是,请将其设为数组。
答案 1 :(得分:3)
如果要多次使用此逻辑,可能需要定义一个Enumerable方法:
module Enumerable
def skip
Enumerator.new do |yielder|
skip_count = 0
each_with_index do |object, index|
if skip_count > 0
skip_count -= 1
else
yielder << object
skip_count = yield(object, index) || 0
end
end
end
end
end
您可以在任何Enumerable
上使用它,您可以指定应跳过的元素数量,具体取决于当前元素和索引。
对于您的示例,您希望每6个元素跳过2个元素(例如4和5)。但是,你想要跳过index = 2
之后的元素(Ruby索引从0开始):
puts ('a'..'z').skip{ |_, index| 2 if (index - 2) % 6 == 0 }.take(8)
# a
# b
# c
# f
# g
# h
# i
# l
答案 2 :(得分:1)
有人可以使用临时累加器:
@lines = (1..12).map(&:to_s)
JUMP_BY = 3
@lines.each.with_index.reduce(0) do |acc, (line, index)|
next acc unless index == acc
puts "line: #{line}"
q, mod = index.divmod(JUMP_BY)
(mod == JUMP_BY - 1) && (q % 2).zero? ? \
(q + 2) * JUMP_BY - 1 : index + 1 # next
end
#⇒ line: 1
# line: 2
# line: 3
# line: 6
# line: 7
# line: 8
# line: 9
# line: 12
通过使JUMP_BY
成为一种方法,人们可以根据需要做出复杂的决定。
答案 3 :(得分:1)
你使它变得比必要的更复杂。你不需要跳过迭代。只要在条件满足(un)时忽略该任务,就转到下一次迭代。
@lines.each_with_index do |line, index|
next if index % 3 == 0
... # do the contentful things
end
答案 4 :(得分:1)
通过在枚举器上使用next,您可以跳过x步
def walk
e = ('a'..'z').each
while e.any?
rand(5).times{e.next}
puts e.peek
end
rescue StopIteration => e
end