2010-07-29 57 views
8

Hãy nói rằng tôi có một phạm vi 0-10:Có cách nào thanh lịch để loại trừ giá trị đầu tiên của dải ô không?

range = 0...10 

Ba chấm có nghĩa là, rằng giá trị cuối cùng (10) bị loại trừ:

range.include? 10 
=> false 

Bây giờ, là có một cách tương tự và thanh lịch để loại trừ giá trị đầu tiên?
Đối với ví dụ ở trên, điều này sẽ có nghĩa là bao gồm tất cả các giá trị mà là lớn (>, không>=) hơn 0 và nhỏ hơn hơn 10

+0

Tôi cho rằng việc loại trừ giá trị cuối cùng thường khá hữu ích như 'range = 0 ... something.size' Usecase của bạn cần loại trừ giá trị _first_ là gì? –

+0

Tôi kiểm tra xem một tập hợp các giá trị nhất định có nằm trong phạm vi đó hay không. Tôi chỉ muốn xử lý các giá trị 0 khác nhau. Tôi biết làm thế nào để đạt được điều này, nhưng tôi đã tò mò, nếu có cái gì đó tương tự như '...' để loại trừ * đầu tiên * giá trị của một phạm vi. –

+0

Tôi đã học được nhiều hơn về phạm vi trong 5 phút so với năm ngoái. Cảm ơn! –

Trả lời

2

số

((0+1)..10) 
+3

Vấn đề duy nhất với điều này là, giá trị giữa 0 và 1 sẽ không được bao gồm. Có, bạn có thể nói '0.00000001..10' (hoặc một cái gì đó tương tự, tùy thuộc vào số lượng thập phân bạn cần). Nhưng điều đó khá xấu xí, IMO, khi điều tôi muốn nói là: '0

+4

Vì Ruby 2.2 bạn có thể sử dụng '(0.0) .next_float..10.0' – Envek

+0

Hoặc, cú pháp ưa thích của tôi:' 0.to_f.next_float..10' – Danyel

0

lẽ bạn có thể tạo loại phạm vi của riêng mình.

class FancyRange 
    def initialize(minimum, maximum, exclusive_minimum, exclusive_maximum) 
    # insert code here 
    end 

    # insert more code here 

end 
5

Tôi có hai đề xuất cho bạn, chúng không lý tưởng lắm nhưng chúng là điều tốt nhất tôi có thể nghĩ đến.

Trước tiên, bạn có thể xác định một phương pháp mới trên lớp Phạm vi làm những gì bạn mô tả. Nó sẽ giống như thế này:

class Range 
    def have?(x) 
    if x == self.begin 
     false 
    else 
     include?(x) 
    end 
    end 
end 

p (0..10).have?(0)  #=> false 
p (0..10).have?(0.00001) #=> true 

Tôi không biết, tôi vừa sử dụng từ đồng nghĩa "bao gồm" làm tên phương thức, có thể bạn có thể nghĩ về điều gì đó tốt hơn. Nhưng đó là ý tưởng.

Và sau đó bạn có thể làm điều gì đó phức tạp hơn và xác định phương thức trên lớp Phạm vi đánh dấu phạm vi là một phạm vi bạn muốn loại trừ giá trị bắt đầu và sau đó thay đổi phương thức include? của Phạm vi để kiểm tra nhãn đó.

class Range 
    def exclude_begin 
    @exclude_begin = true 
    self 
    end 

    alias_method :original_include?, :include? 
    def include?(x) 
    return false if x == self.begin && instance_variable_defined?(:@exclude_begin) 
    original_include?(x) 
    end 

    alias_method :===, :include? 
    alias_method :member?, :include? 
end 

p (0..10).include?(0)      #=> true 
p (0..10).include?(0.00001)    #=> true 
p (0..10).exclude_begin.include?(0)  #=> false 
p (0..10).exclude_begin.include?(0.00001) #=> true 

Một lần nữa, bạn có thể muốn có một tốt hơn (thêm thanh lịch?) Tên cho phương pháp hơn exclude_begin, tôi chỉ chọn đó vì nó phù hợp với phương pháp Phạm vi của exclude_end?.

Chỉnh sửa: Tôi có một số khác cho bạn, chỉ vì tôi thấy vấn đề này thật thú vị. : P này sẽ chỉ làm việc trong phiên bản mới nhất của Ruby 1.9, nhưng sẽ cho phép cú pháp sau:

(0.exclude..10).include? 0  #=> false 
(0.exclude..10).include? 0.00001 #=> true 

Nó sử dụng các ý tưởng tương tự như đề nghị thứ 2 của tôi, nhưng các cửa hàng "trừ điểm đánh dấu" trong số thay vì phạm vi. Tôi phải sử dụng SimpleDelegator của Ruby 1.9 để thực hiện điều này (số riêng của chúng không thể có các biến mẫu hoặc bất kỳ thứ gì), đó là lý do tại sao nó không hoạt động trong các phiên bản trước của Ruby.

require "delegate" 

class Numeric 
    def exclude 
    o = SimpleDelegator.new(self) 
    def o.exclude_this?() true end 
    o 
    end 
end 

class Range 
    alias_method :original_include?, :include? 
    def include?(x) 
    return false if x == self.begin && 
        self.begin.respond_to?(:exclude_this?) && 
        self.begin.exclude_this? 
    original_include?(x) 
    end 

    alias_method :===, :include? 
    alias_method :member?, :include? 
end 
+0

Ồ. Đó là một câu trả lời tuyệt vời. Cảm ơn rất nhiều! Tôi vẫn đang cố gắng hiểu giải pháp Ruby 1.9 của bạn. Thật tuyệt vời khi thấy những gì có thể. Tuy nhiên, tôi nghĩ rằng giải pháp thanh lịch và rõ ràng nhất IMO sẽ là mô tả một phạm vi không bao gồm giá trị bắt đầu và kết thúc bằng bốn dấu chấm: '0 .... 10'. Tôi thực sự không chắc chắn nếu điều này thậm chí có thể mà không rối tung xung quanh với các tập tin range.c !? –

+0

Vâng, tôi đồng ý rằng đó sẽ là một cú pháp tốt đẹp, nhưng nó sẽ đòi hỏi một sự thay đổi về ngữ pháp Ruby (nó gây ra một lỗi cú pháp nếu bạn gõ nó vào). Một điều bạn có thể làm gần đó trong Ruby 1.9 là sử dụng ví dụ cuối cùng của tôi ở đó, nhưng đặt tên cho phương thức 'call' thay vì' exclude'. Sau đó, bạn có thể sử dụng đường cú pháp mới của Ruby và viết '0.() .. 10' và nhận được điều tương tự. '0.()' Là một phím tắt cho phương thức 'call'. Tôi không biết nếu đó là tốt hơn hay không, mặc dù. : P –

+0

Vâng, tốt đẹp. Nhưng điều này có nghĩa là tổng số nhầm lẫn, tôi đoán vậy. ;-) Tôi muốn gắn bó với các giải pháp '(0..10) .exclude_begin' hoặc' 0.exclude..10' của bạn. Cảm ơn câu trả lời của bạn một lần nữa. Tôi đã học được rất nhiều. (Tôi chấp nhận một câu trả lời khác, bởi vì tôi sẽ không mô tả điều này như một giải pháp thanh lịch tương tự như ký hiệu ba chấm để loại trừ giá trị cuối cùng). –

Các vấn đề liên quan