首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Ruby 迴圈語句完整指南:while/until/for/each/times/upto/downto/step 與控制流關鍵字

     編輯:更多程式設計知識

Ruby 迴圈分類總覽

類別關鍵字/方法特性適用場景
條件迴圈while / until前置判斷、支援 begin-end 後置未知迴圈次數、條件複雜
枚舉迴圈for ... in語法糖,內部呼叫 each簡單遍歷、初學者友善
整數迴圈times / upto / downto / step數值範圍、步長控制計數、索引迴圈
集合迴圈each / each_with_index / map 等區塊語法、函數式風格陣列、Hash、Range、自訂類別
流程控制break / next / redo / retry改變迴圈執行流程提前結束、跳過、重試

while / until 迴圈

基本語法


# while:條件為真時執行
i = 0
while i < 5
  puts i
  i += 1
end

# until:條件為假時執行(等同 while not condition)
i = 0
until i >= 5
  puts i
  i += 1
end

單行寫法


# 單行 while/until(需用 begin-end 或修飾語)
i = 0
puts i += 1 while i < 5  # 修飾語形式,先執行再判斷

# 等價於
begin
  puts i += 1
end while i < 5

後置判斷:begin ... end while/until


# 至少執行一次
begin
  print "繼續? (y/n): "
  answer = gets.chomp
end while answer != 'n'

for ... in 迴圈


# 遍歷 Range
for i in 1..5
  puts i
end

# 遍歷陣列
for item in ['apple', 'banana', 'cherry']
  puts item
end

# 遍歷 Hash
for key, value in {a: 1, b: 2}
  puts "#{key}: #{value}"
end

注意:for 不建立新作用域,迴圈變數會洩漏到外部:


for i in 1..3
  x = i * 2
end
puts x  # => 6 (x 仍存在!)
# vs each 區塊建立新作用域

整數迴圈方法

times:固定次數


5.times { |i| print i }  # 01234
5.times do |i|
  puts "第 #{i+1} 次"
end

upto / downto:範圍迴圈


1.upto(5) { |i| print i }   # 12345
5.downto(1) { |i| print i } # 54321

# 等價於
(1..5).each { |i| print i }
(1..5).reverse_each { |i| print i }

step:指定步長


0.step(10, 2) { |i| print i }  # 0246810
10.step(0, -2) { |i| print i } # 1086420

# Range step
(0..10).step(2) { |i| print i }

集合迴圈:each 系列


# 陣列
[1,2,3].each { |x| puts x }
[1,2,3].each_with_index { |x,i| puts "#{i}: #{x}" }

# Hash
{a: 1, b: 2}.each { |k,v| puts "#{k}=#{v}" }
{a: 1, b: 2}.each_key { |k| puts k }
{a: 1, b: 2}.each_value { |v| puts v }

# Range
(1..3).each { |i| puts i }
('a'..'c').each { |c| puts c }

流程控制關鍵字

關鍵字作用範圍範例
break跳出最內層迴圈while/until/for/each/times...找到目標提前結束
next跳過本次迴圈,進入下一次所有迴圈跳過無效資料
redo重新執行本次迴圈(不重新評估條件/迭代器)所有迴圈輸入驗證重試
retry重新開始整個迴圈(重新評估條件/迭代器)begin-rescue 區塊例外處理後重試

break / next 範例


# 找到第一個偶數就停止
[1,3,5,6,7].each do |n|
  break if n.even?
  puts n
end
# 輸出: 1, 3, 5

# 跳過偶數
[1,2,3,4,5].each do |n|
  next if n.even?
  puts n
end
# 輸出: 1, 3, 5

redo 範例:輸入驗證


3.times do |i|
  print "輸入正整數: "
  input = gets.chomp
  unless input =~ /^\d+$/ && input.to_i > 0
    puts "無效,重新輸入"
    redo  # 重新執行同一次迴圈
  end
  puts "第 #{i+1} 個: #{input}"
end

retry 範例:網路請求重試


attempts = 0
begin
  attempts += 1
  response = HTTP.get("https://api.example.com/data")
rescue TimeoutError => e
  if attempts < 3
    puts "超時,重試 (#{attempts}/3)"
    retry  # 重新執行 begin 區塊
  else
    raise
  end
end

進階迴圈模式

多重賦值與解構


# 陣列解構
[[1,2], [3,4]].each { |a,b| puts a+b }  # 3, 7

# Hash 解構
{a: 1, b: 2}.each { |k,v| puts "#{k}=#{v}" }

# 索引與值
%w[a b c].each.with_index(1) { |v,i| puts "#{i}. #{v}" }

無限迴圈


# loop 方法(Kernel 模組)
loop do
  print "> "
  cmd = gets.chomp
  break if cmd == 'exit'
  puts "執行: #{cmd}"
end

# while true
while true
  # ...
end

Enumerator 與鏈式呼叫


# 建立枚舉器
enum = 1.upto(10)
enum.each { |i| puts i }

# 鏈式:with_index, with_object, slice_after 等
(1..10).each_slice(3).to_a  # [[1,2,3], [4,5,6], [7,8,9], [10]]
%w[a b c d].each_cons(2).to_a  # [["a","b"], ["b","c"], ["c","d"]]

效能比較


require 'benchmark/ips'

N = 1_000_000

Benchmark.ips do |x|
  x.report("while") { i=0; while i each > for
# 區塊呼叫有微小開銷,for 內部轉 each 最慢

常見錯誤與最佳實務

  1. 修改迴圈中正在迭代的集合:會導致不可預期行為,改用 dup 或建立新集合
  2. for 迴圈變數洩漏:偏好 each 區塊建立新作用域
  3. 無限迴圈無 break:確保有終止條件
  4. redo/retry 濫用:僅用於輸入驗證、重試邏輯
  5. 大量資料用 each:考慮 find_each (ActiveRecord)、Enumerator::Lazy

函數式替代方案


# 迴圈 -> 方法鏈
(1..10).select(&:even?).map { |x| x*2 }.sum  # 110

# 累積
(1..5).inject(0) { |sum, n| sum + n }  # 15
(1..5).reduce(:+)  # 15
[1,2,3].each_with_object([]) { |x, arr| arr << x*2 }  # [2,4,6]

總結

Ruby 提供豐富的迴圈構造:條件迴圈用 while/until,計數用 times/upto/downto/step,集合遍歷用 each 系列。流程控制 break/next/redo/retry 語義清晰。現代 Ruby 風格偏好區塊式迭代器而非 for 迴圈,利用 Enumerable 模組的強大方法鏈(map, select, reduce 等)寫出更具宣告式、可組合的程式碼。理解作用域差異、效能特性、函數式替代方案,能根據場景選擇最適合的迴圈寫法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved