Range 表示一段值的区间——(1..10) 表示数字,('a'..'z') 表示字母,等等。Range 是带有许多实用方法的对象,可用于迭代、切片、成员判断以及 case 匹配。它是 Ruby 中一个简洁而富有表现力的特性。
创建 Range(.. 与 ...)
(..)
(...)
(..)
关键区别:.. 包含末端,... 排除末端(第三个点把末端“推开”了)。这是一个常需记住的点。
(1..5).each { |n| puts n } # iterate — 1 to 5
(1..5).to_a # [1, 2, 3, 4, 5] — convert to an array
(1..10).map { |n| n * 2 } # ranges support Enumerable methods
(1..100).sum # 5050
(1..10).select(&:even?) # [2, 4, 6, 8, 10]
Range 包含了 Enumerable,因此支持 each、map、select 等方法——而 to_a 会把它实例化为一个数组。
(1..100).include?(50) # true
(1..100).cover?(50) # true — faster (doesn't iterate, just checks endpoints)
age = 25
(18..65).include?(age) # check if a value falls in a range
include?/cover? 能高效地判断成员关系(尤其是 cover?,它只检查端点而不进行迭代)。
# case/when with ranges — clean range-based branching
grade = case score
when 90..100 then "A"
when 80..89 then "B"
when 0..79 then "F"
end
# array/string slicing with ranges
[10, 20, 30, 40, 50][1..3] # [20, 30, 40] — slice by range
"hello world"[0..4] # "hello" — substring by range
# endless/beginless ranges (Ruby 2.6+)
arr[2..] # from index 2 to the end
(1..) # 1 to infinity (with lazy evaluation)
Range 是 Ruby 中一个实用且富有表现力的特性,被用于许多常见场景,因此理解它是有价值的日常知识。
它能简洁地表示区间(数字、字母),并出现在若干常见场景中:迭代((1..5).each——遍历一段序列的简洁方式)、对数组和字符串进行切片(arr[1..3]、str[0..4]——优雅地提取子序列)、成员判断(include?/cover?——检查某个值是否落在区间内,其中 cover? 因只检查端点而高效),尤其是 case/when 匹配(基于区间的清晰分支,例如按分数区间评定等级——一种常见且易读的模式)。
理解重要的 **..(包含)与 ...(排除)**之间的区别,对于正确使用 Range 是必要的(这也是一个常见的困惑点)。
知道 Range 包含了 Enumerable(因此支持 map/select 等),知道如何用它进行迭代、切片、成员判断和 case 匹配,以及现代特性(无尽/无始 Range),就涵盖了它的实际用途。
由于 Range 在地道的 Ruby 中频繁出现(迭代、切片、基于区间的条件判断、值区间的校验),又因为它是处理区间的一种简洁而富有表现力的方式,理解 Range——它的语法(包含与排除)、方法以及常见用途(迭代、切片、成员判断、case 匹配)——是编写干净、地道、能优雅处理序列和区间的 Ruby 代码的实用且切合实际的知识。