Aralık oluşturmada '..' (çift nokta) ve '…' (üç nokta) arasındaki fark nedir?


111

Ruby ve Ruby on Rails öğrenmeye yeni başladım ve aralıkları kullanan doğrulama koduyla karşılaştım:

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

İlk başta farkın uç noktaların dahil edilmesinde olduğunu düşünmüştüm, ancak baktığım API belgelerinde, bunun olup olmadığı ..veya ...her zaman uç noktaları içerdiği önemli görünmüyordu .

Bununla birlikte, irb'de bazı testler yaptım ve ..her iki uç noktayı da ...içerdiğini, ancak üst sınırı değil sadece alt sınırı içerdiğini gösteriyor gibiydi . Bu doğru mu?

Yanıtlar:


157

Range için dokümantasyon bu diyor ki:

..Baştan sona dahil olmak üzere çalıştırma kullanılarak oluşturulan aralıklar . Kullanılarak oluşturulanlar ...son değeri hariç tutar.

Yani a..bgibidir a <= x <= boysa a...bgibidir a <= x < b.


O, ise dikkat to_atamsayılar bir koleksiyon verir tamsayılar bir Range üzerinde bir Aralığı değil değerler kümesi, ancak başlangıç / bitiş değerlerinin basitçe bir çift:

(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


Dokümanlar bunu içermiyordu, bunun yerine Kazmanın Menziller hakkındaki bölümünü okumayı gerektiriyordu . Bu güncellemeyi not ettiğiniz için @MarkAmery'ye ( aşağıya bakın ) teşekkürler .


11
Yukarıdakinden daha iyi / daha az kafa karıştırıcı örnek: (1..10).include? 10 #=> trueve(1...10).include? 10 #=> false
timmcliu

@timmcliu (a..b) != (a...(b+1))Dizi temsillerinin eşit olmasına rağmen (a, b ∈ ℤ olduğunda) bunu göstermekle ilgili olmasa da . Bunu genişletmek için cevabımı biraz güncelledim.
Andrew Marshall

Aralık bir değerler kümesi değilse, o zaman neden bu kod parçası Aralığı bir değer kümesi olarak ele alıyor: (1..5) .inject {| sum, n | sum + n}
VaVa

2
@ValentinVassilev Aralığı bir dizi değer değildir, ancak bunları oluşturabilir. injectgelir Enumerableki Rangeiçerir; uygular , Enumerablekullanır . Tarafından oluşturulan liste hiçbir zaman nesnenin kendi içinde yer almaz. #eachRangeRange#eachRange
Andrew Marshall

6

Bu doğru.

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]

Üç nokta sözdizimi daha az yaygındır, ancak daha iyidir (1..10-1).to_a


12
Bence daha fazla noktanın, aralığın daha az değeri temsil ettiği anlamına gelmesi gerçekten tuhaf . Sanırım sadece bu ..daha yaygın ve bu nedenle daha az tercih ediliyor ?
Andrew Marshall

2
@Andrew: Ben de öyle düşünmüştüm, ama belki de iki nokta çeşidinin daha yaygın olarak arzu edilmesine ve dolayısıyla yazmanın daha kısa olmasına bağlıdır?
safetycopy

1
Ayrıca, (a..b-1) != (a...b)bu cevabın öyle olduklarını ima etmesine rağmen unutmayın .
Andrew Marshall

1
(a..b-1) == (a ... b) yalnızca a ve b'nin tamsayı olduğu ve aralıkları dizilere numaralandırdığınız durumda. (1.0 ... 3.5) aralığını düşünün - 3.5'ten hemen önceki değer nedir? Kesinlikle 2.5 değil!
Chris Heald

3

API belgeleri artık bu davranışı açıklamaktadır:

..Baştan sona dahil olmak üzere çalıştırma kullanılarak oluşturulan aralıklar . Kullanılarak oluşturulanlar ...son değeri hariç tutar.

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

Diğer bir deyişle:

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...b hariç uç değeri olurken, a..b içeren uç değer.

Tamsayılarla çalışırken şu şekilde a...bdavranır 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

Ama gerçekte aralıklar gerçek bir sayı doğrusunda farklılık gösterir .

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

Kesirli adımlarla artırırken bunu görebilirsiniz.

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

1
Düzenlemeden sonra hala yanlış. a& bTamsayı olsa bile , aralıklar farklıdır. Sadece her biri bir diziye dönüştürüldüğünde aynıdırlar. Kabul edilen cevapta belirli bir karşı örnek mevcuttur.
Andrew Marshall

2
@AndrewMarshall Bu örnekle söylemek istediğim şey (ama çok açık değil) tamsayı ölçeğinde olduğu gibi davranıyor. Cevabınızda belirtildiği gibi, daha kesin bir kesirli ölçekte durum böyle değildir. Sanırım aralıklar çoğunlukla tamsayı ölçeğinde kullanılıyor, bu yüzden böyle bir açıklamanın yardımcı olduğuna inanıyorum.
Dennis

-4

.. ve ... bir aralığı gösterir.

Sadece irb'de görün:

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
Yine de soruya gerçekten cevap vermiyor; her ikisi de aralıklar olarak tanımlanmıştır. Kapsayıcı ve Ayrıcalıklı ürün yelpazesi.
Craig Ringer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.