Ruby 范围
Ruby Range(范围):表达序列和区间
Section titled “Ruby Range(范围):表达序列和区间”Range 是 Ruby 中一个强大的特性,用于表示一系列值或一个区间。它们常用于迭代、条件逻辑以及检查值是否在特定边界内。
Ruby 支持两种类型的 Range 字面量:
- 包含结束值的 Range (
..):start..end创建一个包含start和end两个值的 Range。 - 不包含结束值的 Range (
...):start...end创建一个包含start值但不包含end值的 Range。
创建 Range 的示例:
inclusive_numbers = (1..5) # Represents 1, 2, 3, 4, 5 # 代表 1, 2, 3, 4, 5exclusive_numbers = (1...5) # Represents 1, 2, 3, 4 # 代表 1, 2, 3, 4
alphabetic_range = ('a'..'d') # Represents 'a', 'b', 'c', 'd' # 代表 'a', 'b', 'c', 'd'Range 作为序列:
Section titled “Range 作为序列:”Range 非常适合定义序列。你可以使用 to_a 将 Range 转换为数组,或者直接对其进行迭代。
#!/usr/bin/ruby
range1_array = (1..5).to_aputs "range1_array: #{range1_array.inspect}" # Output: range1_array: [1, 2, 3, 4, 5] # 输出: range1_array: [1, 2, 3, 4, 5]range2_array = ('bar'...'bat').to_a # 'bat' is excluded # 'bat' 被排除在外puts "range2_array: #{range2_array.inspect}" # Output: range2_array: ["bar", "bas"] # 输出: range2_array: ["bar", "bas"]
puts "Iterating over a range:"# 迭代一个 range:('A'..'C').each do |letter| puts "Letter: #{letter}"end迭代输出:
Letter: ALetter: BLetter: CRange 有一些用于处理序列的有用方法:
#!/usr/bin/ruby
digits = 0..9
puts "digits.include?(5): #{digits.include?(5)}" # Output: digits.include?(5): true # 输出: digits.include?(5): trueputs "digits.cover?(10.5): #{digits.cover?(10.5)}" # Output: digits.cover?(10.5): false (10.5 is outside 0..9) # 输出: digits.cover?(10.5): false (10.5 不在 0..9 范围内)puts "digits.cover?(5): #{digits.cover?(5)}" # Output: digits.cover?(5): true # 输出: digits.cover?(5): true
puts "Minimum value: #{digits.min}" # Output: Minimum value: 0 # 输出: 最小值: 0puts "Maximum value: #{digits.max}" # Output: Maximum value: 9 # 输出: 最大值: 9
# `reject` works if the range elements can be iterated (like discrete numbers or chars)# `reject` 方法适用于 range 的元素可以迭代的情况 (比如离散的数字或字符)rejected_values = digits.reject { |i| i < 5 }puts "Rejected values (i < 5): #{rejected_values.inspect}" # Output: Rejected values (i < 5): [5, 6, 7, 8, 9] # 输出: 被 reject 的值 (i < 5): [5, 6, 7, 8, 9]include? vs. cover?: 对于 Range,cover?(value) 检查 value 是否在 begin 和 end 之间(对于 .. Range 包含 end,对于 ... Range 不包含 end)。include?(value)(别名为 member?)检查如果将 Range 迭代,value 是否是其中一个元素。对于简单的数字/字符 Range,它们的行为通常相似,但 cover? 可以更高效,并且适用于连续的 Range(例如,浮点数 Range),而 include? 可能未定义。
Range 作为条件(在 case 语句中):
Section titled “Range 作为条件(在 case 语句中):”Range 经常用于 case 语句中,以检查值是否落在特定区间内。这是一种非常地道的 Ruby 写法。
#!/usr/bin/ruby
def categorize_score(score) result = case score when 90..100 then "Excellent (A)" when 80..89 then "Good (B)" when 70..79 then "Average (C)" when 60..69 then "Needs Improvement (D)" when 0..59 then "Failing (F)" else "Invalid Score" end puts "Score #{score}: #{result}"end
categorize_score(95)categorize_score(72)categorize_score(-10)输出:
Score 95: Excellent (A)Score 72: Average (C)Score -10: Invalid Score“Flip-Flop” 运算符(小众用法):
Ruby 有一个不太常见的条件结构,使用 Range 称为“flip-flop”运算符(在 if 等条件上下文中使用的 condition1..condition2 或 condition1...condition2)。它在 condition1 变为真之前一直评估为 false,然后评估为 true 直到 condition2 变为真,之后再重置为 false。由于可能引起混淆,在现代 Ruby 中很少使用,并且通常可以用更清晰的状态机逻辑替代。我们在此提及它只是为了完整性,但不建议随意使用。
# Example of flip-flop (use with caution):# Flip-flop 示例(谨慎使用):# lines = ["header", "data1", "start_section", "content1", "content2", "end_section", "footer"]# lines.each_with_index do |line, index|# if (line.include?('start_section'))..(line.include?('end_section'))# puts "Processing within section: #{line}"# end# endRange 作为区间(使用 ===):
Section titled “Range 作为区间(使用 ===):”case equality 运算符 === 可以与 Range 一起使用,以测试值是否落在 Range 所代表的区间内。对于大多数标准 Range 的实际用途来说,range === value 等同于 range.cover?(value)。
#!/usr/bin/ruby
numeric_range = 1..10char_range = 'a'..'j'
puts "5 lies in (1..10): #{numeric_range === 5}" # Output: 5 lies in (1..10): true # 输出: 5 位于 (1..10) 中: trueputs "15 lies in (1..10): #{numeric_range === 15}" # Output: 15 lies in (1..10): false # 输出: 15 位于 (1..10) 中: false
puts "'c' lies in ('a'..'j'): #{char_range === 'c'}" # Output: 'c' lies in ('a'..'j'): true # 输出: 'c' 位于 ('a'..'j') 中: trueputs "'z' lies in ('a'..'j'): #{char_range === 'z'}" # Output: 'z' lies in ('a'..'j'): false # 输出: 'z' 位于 ('a'..'j') 中: false
# This is how case statements use ranges:# case value# when 1..10 # implicitly (1..10) === value# ...# 这就是 case 语句使用 range 的方式:# case value# when 1..10 # 隐式地执行 (1..10) === value# ...# end实际应用:
Range 用于:生成用于循环的数字或字符序列、定义用于验证的有效输入范围(例如,年龄在 18 到 65 岁之间)、在 case 语句中划分数据、对数组或字符串进行切片(slicing)、以及表示时间间隔。它们的简洁性使得 Ruby 代码更富有表现力。