Bộ đếm tự động trong Ruby cho mỗi?


134

Tôi muốn sử dụng một for-every và counter:

i=0
for blah in blahs
    puts i.to_s + " " + blah
    i+=1
end

Có cách nào tốt hơn để làm điều đó?

Lưu ý: Tôi không biết blahslà một mảng hay hàm băm, nhưng phải làm blahs[i]nó sẽ không khiến nó quyến rũ hơn nhiều. Ngoài ra tôi muốn biết cách viết i++bằng Ruby.


Về mặt kỹ thuật, câu trả lời của Matt và Squeegy xuất hiện đầu tiên, nhưng tôi đang đưa ra câu trả lời tốt nhất cho paradoja để lan truyền xung quanh các điểm một chút về SO. Ngoài ra câu trả lời của anh ta có ghi chú về các phiên bản, vẫn còn có liên quan (miễn là Ubuntu 8.04 của tôi đang sử dụng Ruby 1.8.6).


Nên sử dụng puts "#{i} #{blah}"mà gọn gàng hơn nhiều.


Không có toán tử gia tăng trong Ruby. Số n + = 1 bạn đã viết lên tương đương gần nhất. Nó sẽ phải là đường cú pháp cho n + = 1, chính nó là tốc ký cho n = n + 1. Ý tưởng về ++ đã bị từ chối vì nó che giấu thực tế là bạn đang gán lại biến. rubyurl.com/Dsb1
Chuck

Đẹp! Cảm ơn Chuck. Tôi đã buộc phải học ++ i và i ++ trong Java, vì vậy tôi chỉ nghĩ rằng nó sẽ luôn ở đó.
Dan Rosenstark

Câu trả lời:


190

Như mọi người đã nói, bạn có thể sử dụng

each_with_index

nhưng nếu bạn muốn các chỉ mục với một trình vòng lặp khác với "mỗi" (ví dụ: nếu bạn muốn ánh xạ với một chỉ mục hoặc một cái gì đó tương tự), bạn có thể nối các liệt kê với phương thức Each_with_index hoặc đơn giản là sử dụng with_index:

blahs.each_with_index.map { |blah, index| something(blah, index)}

blahs.map.with_index { |blah, index| something(blah, index) }

Đây là điều bạn có thể làm từ ruby ​​1.8.7 và 1.9.


1
Điều đáng chú ý là điều này là mới trong 1.9.
Zach Langley

1
Cũng phát hiện ra. Trên thực tế, đó cũng là phiên bản 1.8.7, nhưng đó là thứ đáng để thêm vào.
paradoja

Tại sao tôi lại dùng Ruby 1.8.6 nếu tôi chỉ cài đặt toàn bộ trên Ubuntu? Là 1.8.7 thử nghiệm / beta?
Dan Rosenstark

Bạn đang sử dụng Ubuntu nào? Trong Intrepid có 1.8.7. Đây là phiên bản ổn định cuối cùng ( ruby-lang.org/en/doads ). Tuy nhiên, bạn có thể sử dụng khỉ ruby ​​1.8.6 để có hành vi tương tự (xem nghiêm ngặtyyped.com / 2008/09 / ruby-18s-enumerator- class.html ).
paradoja

3
Tôi cảm thấy mệt mỏi vì việc phân phối bị chậm lại nên tôi bắt đầu sử dụng rvm để quản lý cài đặt Ruby của mình trên Ubuntu và Linux Mint.
Tin Man

55
[:a, :b, :c].each_with_index do |item, i|
  puts "index: #{i}, item: #{item}"
end

Bạn không thể làm điều này với. Tôi thường thích cuộc gọi khai báo nhiều hơn cho mỗi cá nhân. Một phần vì dễ dàng chuyển sang các hình thức khác khi bạn đạt đến giới hạn của cú pháp.


Thật tuyệt, tôi thấy quan điểm về các giới hạn với cú pháp for. Tôi phải làm quen với các khối có nhiều tham số.
Dan Rosenstark

11

Vâng, đó là collection.eachđể thực hiện các vòng lặp, và sau đó each_with_indexđể có được chỉ số.

Có lẽ bạn nên đọc một cuốn sách Ruby vì đây là Ruby cơ bản và nếu bạn không biết nó, bạn sẽ gặp rắc rối lớn (thử: http://poignantguide.net/ruby/ ).

Lấy từ mã nguồn Ruby:

 hash = Hash.new
 %w(cat dog wombat).each_with_index {|item, index|
   hash[item] = index
 }
 hash   #=> {"cat"=>0, "wombat"=>2, "dog"=>1}

Không vấn đề, tôi săn long giup. Không có nghĩa là "có nghĩa" về khối .each - đây là những cấu trúc ruby ​​cơ bản và việc học chúng một cách nhanh chóng sẽ thực sự rất đau đớn. :) Tốt nhất để cắn viên đạn và dành một vài giờ đọc!
Matt Rogish

6

Nếu bạn không có phiên bản mới each_with_index, bạn có thể sử dụng zipphương pháp để ghép các chỉ mục với các thành phần:

blahs = %w{one two three four five}
puts (1..blahs.length).zip(blahs).map{|pair|'%s %s' % pair}

sản xuất:

1 one
2 two
3 three
4 four
5 five

1
Tôi có thể tìm mã này ở đâu từ câu trả lời của bạn '%s %s' % [1, "two"]trong tài liệu Ruby? Cảm ơn sự giúp đỡ của bạn và bảo tồn không gian dọc bằng cách sử dụng một dòng để nén và ánh xạ.
Dan Rosenstark

1
Trong ngữ cảnh này, toán tử% -sign là một phương thức của lớp String. Bạn có thể đọc về nó tại ruby-doc.org/core/groupes/String.html#M000770 . Hoặc bạn có thể nhập ri String #% tại dấu nhắc lệnh. Hoặc bạn có thể nhập ri% để xem tất cả các lớp tài liệu nhận ra nó, ví dụ, ý nghĩa quen thuộc hơn ở ri Fixnum #%.
George

4

Đối với câu hỏi của bạn về việc làm i++, tốt, bạn không thể làm điều đó trong Ruby. Các i += 1tuyên bố bạn đã là chính xác như bạn đang phải làm điều đó.



1

Nếu blahslà một lớp kết hợp trong Vô số, bạn sẽ có thể làm điều này:

blahs.each_with_index do |blah, i|
  puts("#{i} #{blah}")
end

1

Nếu bạn muốn lấy chỉ số ruby ​​cho từng loại, thì bạn có thể sử dụng

.each_with_index

Dưới đây là một ví dụ để cho thấy cách .each_with_indexhoạt động:

range = ('a'..'z').to_a
length = range.length - 1
range.each_with_index do |letter, index|
    print letter + " "
    if index == length
        puts "You are at last item"
    end
end

Điều này sẽ in:

a b c d e f g h i j k l m n o p q r s t u v w x y z You are at last item
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.