Ruby Range 范围
最近一直在做 生理周期,不过不要担心,这里只会探讨技术领域,不会涉及到神圣的 MC 领域。在做生理周期指数预测、周期日报的时候大量用到了 Range 对象,所以干脆就把 Range 对象系统的学习下,在这里记录并分享出来。
Ruby Range
Range 在概念上很直观,即范围,但是在实际使用中可能会遇到一些容易混淆的东西,看下面代码:
# 注意:..操作符将包含上限,而...不包含上限。
(-1 .. -5).to_a #=> []
(-5 .. -1).to_a #=> [-5, -4, -3, -2, -1]
('a' .. 'e').to_a #=> ["a", "b", "c", "d", "e"]
('a' ... 'e').to_a #=> ["a", "b", "c", "d"]
begin / end first / last
使用 first 和 last 方法(或同义方法 begin 和 end),可以获取一个 Range 的开始和结束元素:
r1 = 3 .. 6
r2 = 3 ... 6
r1a, r1b = r1.first, r1.last #=> 3, 6
r1c, r1d = r1.begin, r1.end #=> 3, 6
r2a, r2b = r2.begin, r2.end #=> 3, 6 (注意:不是 3 和 5)
r1.first(2) #=> [3, 4]
exclude_end?
exclude_end?方法可以得到 Range 是否排除上限项(即是否是...的 Range)
r1 = 3 .. 6
r2 = 3 ... 6
r1.exclude_end? #=> false
r2.exclude_end? #=> true
include? / cover?
include?方法(同义方法 member?)或者 cover?方法可以判断一个值是否处在当前的 Range 中:
r = 1 .. 5
r.include?(1) #=> true
r.include?(0) #=> false
r.cover?(1) #=> true
r.cover?(0) #=> false
区别:include?方法是把 Range 的元素迭代取出进行比较,而 cover?
方法只是把给出的值和该 Range 的上下限做比较得出的,所以 cover?
性能比 include?
要好。
step
如果我们想要从 0 .. 20 中取出这样的元素 0,5,10,20 怎么办?这时候 step 方法就用到了
r = 0 .. 20
r.step(5).to_a #=> [0, 5, 10, 15, 20]
浮点数的 Range
浮点数的 Range 可以进行迭代么?我们来看一下:
fr = 2.0..2.2
fr.each {|x| puts x } #=> TypeError: can't iterate from Float
为什么浮点数不可以迭代呢?是因为不能实现么?理论上,这是没有问题的,但是,实际上,如果浮点数 Range 迭代,这有可能出现:很小的一个范围,将产生非常庞大的迭代量。这对语言的实现有非常高的要求。况且,这样的功能,极少有用到。
反向的 Range
我们讨论下限大于上限的 Range,如:
r = 6..3
x = r.begin #=> 6
y = r.end #=> 3
flag = r.end_excluded? #=> false
它确实是个合法的 Range,但是,它包含的内容却并不是我们想像的那样:
arr = r.to_a #=> []
r.each {|x| p x} #=> 无结果
r.include?(5) #=> false
那么说反向 Range 是没有什么用处的咯?那倒不是,我们可以在字符串和数组中使用反向 Range:
string = "flowery"
str1 = string[0..-2] #=> "flower"
str2 = string[1..-2] #=> "lower"
str3 = string[-5..-3] #=> "owe" (其实这是个正向的 Range)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 搭建 Octopress
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论