Skip to content

Ruby 循环

Ruby 循环和迭代器:重复执行操作

Section titled “Ruby 循环和迭代器:重复执行操作”

循环是基本的控制结构,允许你多次执行一段代码。Ruby 提供了传统的循环关键字,以及更符合 Ruby 习惯的强大迭代器方法。

Ruby 开发者通常更喜欢使用集合(如 Array 和 Hash)和其他对象提供的迭代器方法,而不是传统的循环结构。迭代器简洁、富有表现力,并且通常能更好地管理作用域(scope)。

each 迭代器:

each 迭代器是最常用的迭代器之一。它遍历集合中的每个元素。

#!/usr/bin/ruby
fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
puts "I love #{fruit}s!"
end
# Short block syntax:
(1..3).each { |number| puts "Number: #{number}" }

输出:

I love apples!
I love bananas!
I love cherrys!
Number: 1
Number: 2
Number: 3

times 迭代器:

执行代码块指定的次数。

#!/usr/bin/ruby
3.times do |i|
puts "Iteration number #{i + 1}"
end

输出:

Iteration number 1
Iteration number 2
Iteration number 3

其他常用迭代器:map, select, reject, upto, downto 等。它们提供了强大的方式来转换和过滤集合。(更多关于 map, select 等的内容请参阅 Array 章节)

虽然迭代器通常更受欢迎,但 Ruby 也支持传统的循环关键字。

只要条件为真,就执行代码。

语法:

while condition [do]
# code to execute
end

示例:

#!/usr/bin/ruby
count = 0
limit = 3
while count < limit do
puts "Inside the while loop, count = #{count}"
count += 1
end

输出:

Inside the while loop, count = 0
Inside the while loop, count = 1
Inside the while loop, count = 2

语法:

# code to execute while condition
# or more commonly for one-liners:
begin
# code
end while condition

示例:

#!/usr/bin/ruby
value = 0
begin
puts "Value is #{value}"
value += 1
end while value < 3

输出:

Value is 0
Value is 1
Value is 2

只要条件为假(即直到条件变为真),就执行代码。

语法:

until condition [do]
# code to execute
end

示例:

#!/usr/bin/ruby
counter = 5
until counter <= 0 do
puts "Inside the until loop, counter = #{counter}"
counter -= 1
end

输出:

Inside the until loop, counter = 5
Inside the until loop, counter = 4
Inside the until loop, counter = 3
Inside the until loop, counter = 2
Inside the until loop, counter = 1

语法:

# code to execute until condition
begin
# code
end until condition

示例:

#!/usr/bin/ruby
stock = 3
begin
puts "Processing item, stock remaining: #{stock}"
stock -= 1
end until stock == 0

输出:

Processing item, stock remaining: 3
Processing item, stock remaining: 2
Processing item, stock remaining: 1

遍历集合中的元素(或任何响应 each 方法的对象)。

语法:

for loop_variable in expression [do]
# code to execute
end

示例:

#!/usr/bin/ruby
for i in 0..2 # Iterates through the range 0 to 2 (inclusive)
puts "Value of local variable is #{i}"
end
colors = ["red", "green", "blue"]
for color in colors
puts "Color: #{color}"
end

输出:

Value of local variable is 0
Value of local variable is 1
Value of local variable is 2
Color: red
Color: green
Color: blue

注意:for...in 循环大致等同于 (expression).each do |loop_variable| ... end。然而,一个关键区别是 for...in 不会为 loop_variable 创建新的作用域,而 each 配合代码块会创建。出于这个原因以及保持代码一致性,在现代 Ruby 中通常更推荐使用 each。

Ruby 提供了控制循环流程的语句:

break 语句:

立即终止最内层的循环。

#!/usr/bin/ruby
(0..4).each do |i|
if i == 3 then
puts "Breaking at i = #{i}"
break
end
puts "Value of i is #{i}"
end

输出:

Value of i is 0
Value of i is 1
Value of i is 2
Breaking at i = 3

next 语句:

跳过当前迭代的剩余部分,继续最内层循环的下一次迭代。

#!/usr/bin/ruby
(0..4).each do |i|
if i == 2 then
puts "Skipping i = #{i}"
next
end
puts "Value of i is #{i}"
end

输出:

Value of i is 0
Value of i is 1
Skipping i = 2
Value of i is 3
Value of i is 4

redo 语句:

从头重新开始最内层循环的当前迭代,但不重新评估循环的条件(如果有)。

#!/usr/bin/ruby
attempts = 0
(0..2).each do |i|
puts "Attempting task for i = #{i}, attempt ##{attempts + 1}"
if i == 1 && attempts < 2 then
attempts += 1
puts "Redoing for i = #{i}"
redo # Restarts this iteration (for i = 1)
end
puts "Completed task for i = #{i}"
attempts = 0 # Reset for next i
end

输出:

Attempting task for i = 0, attempt #1
Completed task for i = 0
Attempting task for i = 1, attempt #1
Redoing for i = 1
Attempting task for i = 1, attempt #2
Redoing for i = 1
Attempting task for i = 1, attempt #3
Completed task for i = 1
Attempting task for i = 2, attempt #1
Completed task for i = 2

注意:如果不小心使用,redo 很容易导致死循环。它不如 break 或 next 常用。

retry 语句:

retry 语句主要用于 rescue 代码块中,以重新执行发生异常的整个 begin...end 代码块。在循环内部直接使用它(不在 rescue 子句中)是罕见的,并且可能令人困惑,因为它通常会从最开始重新启动整个循环或迭代器。

retry 在 rescue 子句中的示例(其常见用法):

#!/usr/bin/ruby
retries_left = 2
begin
puts "Attempting operation..."
# Simulate an error sometimes
raise "Simulated network error" if rand(3) == 0 && retries_left > 0
puts "Operation successful!"
rescue => e
puts "Error: #{e.message}"
if retries_left > 0
retries_left -= 1
puts "Retrying... (#{retries_left} retries left)"
retry # Restart the begin block
else
puts "No more retries. Operation failed."
end
end

实际应用:

循环和迭代器在各种场景下都广泛使用:处理用户输入、逐行读取文件、迭代数据库记录、渲染 UI 组件、重复执行计算等等。选择合适的循环结构(通常是 each 或 map 等迭代器)可以使你的 Ruby 代码更具可读性和效率。