2012-01-11 18 views

Trả lời

44

Cách dễ nhất để làm điều đó là sử dụng downto

5.downto(1) do |i| puts i end 
+0

Rất tốt, cảm ơn Derek! – larryzhao

+2

Và trong các phiên bản hiện đại của Ruby, bạn có thể làm 'x = 5.downto (1)' và chuyển 'x' xung quanh thành một biến. –

+0

Tốt. một dãy xử lý một khối như một trình lặp tự động một cách tự động. Không cần gọi rõ ràng '.each' – ahnbizcad

20

Phạm vi sử dụng <=> để xác định xem một lần lặp kết thúc; 5 <=> 1 == 1 (lớn hơn), do đó, nó được thực hiện trước khi nó bắt đầu. Ngay cả khi họ không, phạm vi lặp lại bằng cách sử dụng succ; 5.succ6, vẫn hết may mắn. Phạm vi của step không được âm, do đó không hoạt động.

Nó trả về dải vì each trả về giá trị được gọi. Sử dụng downto nếu đó là chức năng mà bạn đang tìm kiếm, nếu không câu trả lời ở trên sẽ trả lời câu hỏi thực tế của bạn về "lý do".

+0

Rất tốt giải thích, bây giờ tôi hiểu tất cả chúng. – larryzhao

1

Điều này thậm chí không thực sự liên quan đến Ruby, nó chỉ đơn giản là toán cơ bản: phạm vi bắt đầu bằng 5 và kết thúc bằng 1 trống. Không có gì để lặp lại.

+2

Có, nhưng tại sao Ruby không đi "chờ một chút, 1 ít hơn 5, thay vào đó hãy ngược lại"? –

+6

ruby ​​rất thân thiện với người dùng, vì vậy sẽ hoàn toàn hợp lý khi mong đợi nó sẽ hoạt động. – ahnbizcad

+1

@AndrewGrimm: bởi vì Ruby không thể nói. Giao thức phạm vi không yêu cầu giá trị phù hợp phải trả về '<=>', chỉ bên trái. –

0

Bởi vì Ruby chỉ làm những gì nó được nói, không phải những gì bạn mean.

Không thể biết bạn có muốn đảo ngược (ví dụ 5, 4, 3, 2, 1) hay không hoặc liệu bạn thực sự chỉ muốn các số bắt đầu từ 5 nhỏ hơn hoặc bằng 1. về mặt lý thuyết có thể ai đó có thể muốn thứ hai, và bởi vì Ruby không thể nói những gì bạn thực sự muốn, nó sẽ đi với thứ hai.

+0

số bắt đầu từ 5 nhỏ hơn hoặc bằng 1 – Neeraj

+1

không mang tính xây dựng. – Hamdan

+1

@Hamdan bạn có thể giải thích tại sao câu trả lời của tôi không mang tính xây dựng? Tôi không gọi ai là thằng ngốc, tôi chỉ giải thích rằng Ruby không hoạt động theo cách mà OP mong đợi. –

3

Bạn có thể dễ dàng mở rộng các lớp Range, đặc biệt là mỗi phương pháp, để làm cho nó tương thích với cả tăng dần và dao động giảm dần:

class Range 
    def each 
    if self.first < self.last 
     self.to_s=~(/\.\.\./) ? last = self.last-1 : last = self.last 
     self.first.upto(last) { |i| yield i} 
    else 
     self.to_s=~(/\.\.\./) ? last = self.last+1 : last = self.last 
     self.first.downto(last) { |i| yield i } 
    end 
    end 
end 

Sau đó, đoạn code sau sẽ thực hiện cũng giống như bạn muốn mong đợi:

(0..10).each { |i| puts i} 
(0...10).each { |i| puts i} 
(10..0).each { |i| puts i} 
(10...0).each { |i| puts i} 
+1

Được mã hóa độc đáo. Rủi ro khi sử dụng phương pháp này là bạn có thể có các thư viện hiện tại, trong đó lập trình viên giả định rằng một phạm vi ngược sẽ không lặp lại, và bằng cách thực hiện thay đổi này, bạn phá vỡ giả định đó và đưa các lỗi vào trong thư viện. Hãy tưởng tượng rằng các giới hạn bên trái và bên phải được biểu diễn bởi các biến, x và y, thay vì Fixnums cố định. Trong trường hợp này, lập trình viên có thể dựa vào hành vi phạm vi "bình thường". Đây là một nguy cơ điển hình khi khỉ vá một lớp trong Ruby. –

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