2012-03-13 16 views
75

Ho appena iniziato l'apprendimento Ruby e Ruby on Rails e mi sono imbattuto il codice di convalida che utilizza gamme:Differenza tra ".." (punto doppio) e "..." (punto triplo) nella generazione dell'intervallo?

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

In un primo momento ho pensato che la differenza era l'inclusione di punti finali, ma nella documentazione API Ho guardato in , non sembrava importare se fosse .. o ...: includeva sempre gli endpoint.

Tuttavia, ho eseguito alcuni test in irb e sembrava indicare che .. includesse entrambi gli endpoint, mentre ... includeva solo il limite inferiore ma non quello superiore. È corretto?

risposta

111

Il documentation for Range dice questo:

Gamme costruiti utilizzando .. corsa dall'inizio alla fine inclusivo. Quelli creati utilizzando ... escludono il valore finale.

Così a..b è come a <= x <= b, mentre a...b è come a <= x < b.


Si noti che, mentre to_a su una serie di numeri interi dà un insieme di numeri interi, un Range è non un insieme di valori, ma semplicemente una coppia di valori di inizio/fine:

(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 


I documenti utilizzati per non includerlo, richiedevano invece la lettura dello Pickaxe’s section on Ranges. Grazie a @MarkAmery (see below) per aver notato questo aggiornamento.

+0

Ho programmato il rubino per 8 anni e non l'ho mai saputo. Grazie! –

+9

Esempio migliore/meno confuso di quanto sopra: '(1..10) .include? 10 # => true' e '(1 ... 10) .include? 10 # => false' – timmcliu

+0

@timmcliu Sebbene non sia rilevante per illustrare il punto che '(a..b)! = (A ... (b + 1))' nonostante le loro rappresentazioni di matrice siano uguali (quando a, b ∈ ℤ). Ho aggiornato la mia risposta un po 'per ampliarla. –

4

Ciò è corretto.

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] 

La sintassi tripla-dot è meno comune, ma è più bello di (1..10-1).to_a

+9

Penso che sia davvero bizzarro che * più * punti indica che l'intervallo rappresenta * meno valori *. Immagino sia solo che '..' è più comune e quindi meno è preferito per questo? –

+2

@Andrew: Anch'io l'ho pensato, ma forse la scelta della varietà a due punti è più comune e quindi più breve da digitare? – safetycopy

+0

Inoltre, si noti che '(a..b-1)! = (A ... b)', sebbene questa risposta implichi che lo siano. –

-4

.. e ... denotano un intervallo.

Basta vederlo in 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

In realtà non risponde alla domanda; entrambi sono descritti come intervalli. * Inclusive * contro * Esclusiva *. –

3

la documentazione API ora descrivere questo comportamento:

intervalli costruiti utilizzando .. corsa dall'inizio alla fine inclusivamente. Quelli creati utilizzando ... escludono il valore finale.

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

In altre parole:

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...besclude il valore finale, mentre a..binclude il valore finale.

Quando si lavora con numeri interi, a...b si comporta come 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 

Ma in realtà gli intervalli differiscono su un real number line.

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

Si può vedere questo quando avanzamento a scatti frazionari.

>> (-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

errato. 'a ... b' è * non * uguale a' a .. (b-1) '. –

+0

Ancora errato dopo la modifica. Anche se 'a' e' b' sono numeri interi, gli intervalli sono diversi. Solo quando ognuno viene convertito in un array sono uguali. Esiste un controesempio specifico nella risposta accettata. –

+2

@AndrewMarshall Quello che intendevo dire con quell'esempio (ma non molto bene evidentemente) è su una scala intera che si comporta in questo modo. Questo non è il caso su una scala frazionaria più precisa, come sottolineato nella tua risposta. Ritengo che le gamme siano spesso utilizzate su una scala intera, motivo per cui credo che una tale spiegazione sia utile. – Dennis

Problemi correlati