Ruby循环控制 #
一、循环控制概述 #
Ruby提供了多种控制循环执行的语句。
| 语句 | 描述 |
|---|---|
| break | 终止循环 |
| next | 跳过当前迭代 |
| redo | 重新执行当前迭代 |
| retry | 重新开始循环 |
二、break #
2.1 基本用法 #
ruby
i = 0
while true
puts i
i += 1
break if i >= 5
end
2.2 在迭代器中使用 #
ruby
[1, 2, 3, 4, 5].each do |n|
break if n > 3
puts n
end
2.3 带返回值 #
ruby
result = [1, 2, 3, 4, 5].each do |n|
break n * 2 if n > 3
end
puts result
2.4 多值返回 #
ruby
result = loop do
break 1, 2, 3
end
result
2.5 嵌套循环中的break #
ruby
for i in 1..3
for j in 1..3
puts "#{i}, #{j}"
break if j == 2
end
end
2.6 实用示例 #
ruby
def find_first(items, condition)
items.each do |item|
return item if condition.call(item)
end
nil
end
find_first([1, 2, 3, 4, 5], ->(n) { n > 3 })
三、next #
3.1 基本用法 #
ruby
(1..10).each do |n|
next if n.even?
puts n
end
3.2 在while中使用 #
ruby
i = 0
while i < 10
i += 1
next if i.even?
puts i
end
3.3 带返回值 #
ruby
result = [1, 2, 3, 4, 5].map do |n|
next nil if n.even?
n * 2
end
result
3.4 在块中使用 #
ruby
def process_items(items)
items.each do |item|
next unless item.valid?
process(item)
end
end
3.5 实用示例 #
ruby
def sum_odd_numbers(numbers)
sum = 0
numbers.each do |n|
next unless n.odd?
sum += n
end
sum
end
sum_odd_numbers([1, 2, 3, 4, 5])
四、redo #
4.1 基本用法 #
ruby
i = 0
while i < 3
i += 1
puts "i = #{i}"
redo if i == 2
end
4.2 在迭代器中使用 #
ruby
retries = 0
[1, 2, 3].each do |n|
puts "处理 #{n}"
retries += 1
redo if retries < 2 && n == 2
retries = 0
end
4.3 输入验证 #
ruby
def get_valid_input
input = nil
loop do
print "请输入数字: "
input = gets.chomp
redo unless input.match?(/\A\d+\z/)
break
end
input.to_i
end
4.4 实用示例 #
ruby
def process_with_retry(items)
items.each do |item|
attempts = 0
begin
puts "处理 #{item}"
raise "失败" if item == 2 && attempts < 2
attempts = 0
rescue
attempts += 1
redo if attempts < 3
puts "跳过 #{item}"
end
end
end
五、retry #
5.1 基本用法 #
ruby
def fetch_data(url)
puts "获取 #{url}"
raise "网络错误"
end
retries = 0
begin
fetch_data("https://example.com")
rescue => e
retries += 1
if retries < 3
puts "重试 #{retries}"
retry
else
puts "失败: #{e.message}"
end
end
5.2 retry vs redo #
ruby
i = 0
while i < 3
i += 1
puts "i = #{i}"
redo if i == 2
end
i = 0
while i < 3
i += 1
puts "i = #{i}"
retry if i == 2
end
5.3 实用示例 #
ruby
def fetch_with_retry(url, max_retries: 3, delay: 1)
retries = 0
begin
response = Net::HTTP.get(URI(url))
JSON.parse(response)
rescue => e
retries += 1
if retries < max_retries
puts "重试 #{retries}/#{max_retries}: #{e.message}"
sleep delay
retry
else
raise "获取失败: #{e.message}"
end
end
end
六、catch和throw #
6.1 基本用法 #
ruby
result = catch :done do
(1..10).each do |i|
(1..10).each do |j|
if i * j == 25
throw :done, [i, j]
end
end
end
nil
end
result
6.2 跳出嵌套循环 #
ruby
catch :break_all do
for i in 1..5
for j in 1..5
puts "#{i}, #{j}"
throw :break_all if i == 3 && j == 3
end
end
end
6.3 错误处理 #
ruby
def process_data(data)
catch :invalid do
data.each do |item|
throw :invalid, "无效数据: #{item}" unless valid?(item)
process(item)
end
"处理完成"
end
end
6.4 实用示例 #
ruby
def search_nested(data, target)
catch :found do
data.each_with_index do |row, i|
row.each_with_index do |cell, j|
throw :found, [i, j] if cell == target
end
end
nil
end
end
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
search_nested(matrix, 5)
search_nested(matrix, 10)
七、return #
7.1 在块中使用return #
ruby
def find(items, target)
items.each do |item|
return item if item == target
end
nil
end
find([1, 2, 3, 4, 5], 3)
7.2 return vs break #
ruby
def with_break
[1, 2, 3, 4, 5].each do |n|
break n if n > 3
end
end
def with_return
[1, 2, 3, 4, 5].each do |n|
return n if n > 3
end
end
with_break
with_return
7.3 lambda vs proc #
ruby
my_lambda = -> { return "lambda返回" }
my_proc = Proc.new { return "proc返回" }
def test_lambda
my_lambda = -> { return "lambda返回" }
result = my_lambda.call
"方法继续执行: #{result}"
end
def test_proc
my_proc = Proc.new { return "proc返回" }
my_proc.call
"这行不会执行"
end
test_lambda
test_proc
八、实用示例 #
8.1 重试机制 #
ruby
def with_retry(max_retries: 3)
retries = 0
begin
yield
rescue => e
retries += 1
if retries < max_retries
puts "重试 #{retries}"
retry
else
raise e
end
end
end
with_retry { risky_operation }
8.2 超时处理 #
ruby
require 'timeout'
def with_timeout(seconds)
Timeout.timeout(seconds) do
yield
end
rescue Timeout::Error
puts "操作超时"
nil
end
with_timeout(5) { long_running_operation }
8.3 进度跟踪 #
ruby
def process_with_progress(items)
total = items.length
processed = 0
items.each do |item|
next unless item.valid?
process(item)
processed += 1
if processed % 100 == 0
puts "进度: #{processed}/#{total}"
end
end
end
8.4 批处理 #
ruby
def process_in_batches(items, batch_size: 100)
items.each_slice(batch_size) do |batch|
batch.each do |item|
next unless item.valid?
process(item)
end
end
end
九、最佳实践 #
9.1 选择合适的控制语句 #
ruby
items.each do |item|
next unless item.valid?
break if item.stop_signal?
process(item)
end
9.2 避免过度使用redo/retry #
ruby
# 不推荐
i = 0
while i < 10
i += 1
redo if some_condition
end
# 推荐
i = 0
while i < 10
i += 1
redo_needed = some_condition
redo if redo_needed
end
9.3 使用catch/throw处理复杂流程 #
ruby
catch :exit do
complex_nested_operations
end
十、总结 #
本章我们学习了:
- break:终止循环,可带返回值
- next:跳过当前迭代
- redo:重新执行当前迭代
- retry:重新开始循环(通常用于异常处理)
- catch/throw:非局部跳转
- return:从方法返回
接下来让我们学习Ruby的迭代器!
最后更新:2026-03-27