2013-11-25 26 views
4

Ruby範圍的.end是用於指定範圍的結束的數字,不管範圍是否「排除」結束。我不明白這個設計決定的基本原理,但從來沒有少,我想知道什麼是最習慣的機制是確定範圍的「有效結束」(即最大整數n,使得range.include?(n)true。唯一的機制我所知道的是last(1)[0],這似乎很klunky如何找到範圍的「有效」結束?

+0

'max'是否提供所需的輸出? – zwippie

+0

是的,它的確如此。謝謝。 –

回答

7

使用Range#max方法:

r = 1...10 
r.end 
# => 10 
r.max 
# => 9 

max不會獨佔範圍內工作,如果任何端點是Float(見range_maxrange.c瞭解詳細信息) :

(1.0...10.0).max 
# TypeError: cannot exclude non Integer end value 

(1.0..10.0).max 
# => 10.0 

作爲例外,如果begin > end,不會引發錯誤和nil返回:

(2.0...1.0).max 
# => nil 


更新:在costant時間max適用於任何包含的範圍和整數的獨家範圍,它分別返回與endend-1相同的值。它也是O(1)如果範圍爲begin > end,在這種情況下返回nil對於非整數對象的範圍(String,Date,...)或者塊通過時,它會調用Enumerable#max,因此它必須移動範圍內的所有元素!

+0

Doh!謝謝。 –

+0

隨着OP要求*整數*,我們可以將'(1.0 ... 10.0)'轉換爲**整數**版本:'r = 1.0 ... 10.0; r2 = Range.new r.begin.to_i,r.end.to_i,r.exclude_end?;'。另一方面,如果我們在'Float'中定義'pred'和'succ',我們可以在其上迭代(例如:'to_a'),所以我們可以使用'minmax',獲得第二個值,並將其轉換爲整數。所以......是的,第一種方法更簡單,更精確。 PS。我們不能使用'max',因爲它檢查*範圍*的元素是否是整數,並且僅與整數一起工作。 –

+1

'.max'是否會傳播範圍內的所有元素? – steenslag