2012-03-13 14 views
75

Właśnie rozpoczął naukę Ruby i Ruby on Rails i natknąłem kod weryfikacyjny, który używa zakresach:Różnica między ".." (podwójna kropka) i "..." (potrójna kropka) w zakresie generowania?

validates_inclusion_of :age, :in => 21..99 
validates_exclusion_of :age, :in => 0...21, :message => "Sorry, you must be over 21" 

Na początku myślałem, że różnica była w włączenie punktów końcowych, ale w docs API Spojrzałem , nie miało to znaczenia, czy było to .. lub ...: zawsze zawierało punkty końcowe.

Jednakże, wykonałem kilka testów w irb i zdawało się wskazywać, że .. zawiera oba punkty końcowe, podczas gdy ... zawiera tylko dolną granicę, ale nie górną. Czy to jest poprawne?

Odpowiedz

111

documentation for Range mówi tak:

Zakresy zbudowane przy użyciu .. biec od początku do końca włącznie. Te utworzone przy użyciu ... wykluczają wartość końcową.

Więc a..b jest jak a <= x <= b, natomiast a...b jest jak a <= x < b.


zauważyć, że podczas gdy to_a na szeregu liczb daje zbiór liczb całkowitych, zakres jest nie zestaw wartości, ale po prostu para wartości start/end:

(1..5).include?(5)   #=> true 
(1...5).include?(5)   #=> false 

(1..4).include?(4.1)   #=> false 
(1...5).include?(4.1)  #=> true 
(1..4).to_a == (1...5).to_a #=> true 
(1..4) == (1...5)   #=> false 


Dokumenty nie zawierały tego, zamiast tego wymagały przeczytania Pickaxe’s section on Ranges. Podziękowania dla @MarkAmery (see below) za odnotowanie tej aktualizacji.

+0

Programowałem ruby ​​przez 8 lat i nigdy o tym nie wiedziałem. Dzięki! –

+9

Lepszy/mniej mylący przykład niż powyższy: '(1..10) .include? 10 # => true' i '(1 ... 10). Include? 10 # => false' – timmcliu

+0

@timmcliu Chociaż nie ma znaczenia dla zilustrowania punktu, w którym '(a..b)! = (A ... (b + 1))' pomimo reprezentacji macierzy są równe (gdy a, b ∈ ℤ). Uaktualniłem moją odpowiedź, aby rozwinąć tę kwestię. –

4

To prawda.

1.9.3p0 :005 > (1...10).to_a 
=> [1, 2, 3, 4, 5, 6, 7, 8, 9] 
1.9.3p0 :006 > (1..10).to_a 
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Składnia triple-kropka jest mniej powszechne, ale jest ładniejszy niż (1..10-1).to_a

+9

Myślę, że to naprawdę dziwne, że * więcej * punktów oznacza, że ​​zakres reprezentuje * mniej * wartości. Chyba po prostu '.. jest bardziej powszechne i dlatego mniej jest dla niego preferowane? –

+2

@Andrew: Też tak pomyślałem, ale może to zależy od tego, czy odmiany o dwóch kropkach są bardziej pożądane, a przez to krótsze w pisaniu? – safetycopy

+0

Należy również zauważyć, że '(a..b-1)! = (A ... b)', chociaż ta odpowiedź implikuje, że tak. –

-4

.. i ... oznaczają zakres.

Wystarczy zobaczyć w IRB:

ruby-1.9.2-p290 :032 > (1...2).each do puts "p" end 
p 
=> 1...2 
ruby-1.9.2-p290 :033 > (1..2).each do puts "p" end 
p 
p 
+2

Ale tak naprawdę nie odpowiada na pytanie; oba są opisane jako zakresy. * Obejmujący * * Ekskluzywny * zasięg. –

3

Docs API teraz opisać to zachowanie:

Zakresy zbudowane przy użyciu .. biec od początku do końca włącznie. Te utworzone przy użyciu ... wykluczają wartość końcową.

- http://ruby-doc.org/core-2.1.3/Range.html

Innymi słowy:

2.1.3 :001 > ('a'...'d').to_a 
=> ["a", "b", "c"] 
2.1.3 :002 > ('a'..'d').to_a 
=> ["a", "b", "c", "d"] 
1

a...bwyklucza wartości końcowej, podczas gdy a..bobejmuje wartość końcowa.

Podczas pracy z liczbami całkowitymi, a...b zachowuje się jak a..b-1.

>> (-1...3).to_a 
=> [-1, 0, 1, 2] 

>> (-1..2).to_a 
=> [-1, 0, 1, 2] 

>> (-1..2).to_a == (-1...3).to_a 
=> true 

Ale tak naprawdę zakresy różnią się na real number line.

>> (-1..2) == (-1...3) 
=> false 

Widać to przy inkrementacji krokami ułamkowymi.

>> (-1..2).step(0.5).to_a 
=> [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0] 

>> (-1...3).step(0.5).to_a 
=> [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5] 
+0

Niepoprawnie. 'a ... b' jest * nie * równe' a .. (b-1) '. –

+0

Nadal niepoprawny po edycji. Nawet jeśli "a" i "b" są liczbami całkowitymi, zakresy są różne. Tylko wtedy, gdy każdy jest konwertowany na tablicę, są one takie same. W akceptowanej odpowiedzi istnieje określony kontrprzykład. –

+2

@AndrewMarshall Co miałem na myśli z tym przykładem (ale niezbyt dobrze ewidentnie) jest na skali całkowitej zachowuje się w ten sposób. Nie dotyczy to dokładniejszej skali ułamkowej, jak wskazano w Twojej odpowiedzi. Sądzę, że zakresy są najczęściej stosowane w skali całkowitej, dlatego uważam, że takie wyjaśnienie jest pomocne. – Dennis

Powiązane problemy