Penghitung otomatis di Ruby untuk masing-masing?

135

Saya ingin menggunakan for-each and a counter:

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

Apakah ada cara yang lebih baik untuk melakukannya?

Catatan: Saya tidak tahu apakah blahsitu array atau hash, tetapi harus melakukannya blahs[i]tidak akan membuatnya lebih seksi. Saya juga ingin tahu cara menulis i++di Ruby.


Secara teknis, jawaban Matt dan Squeegy berada di urutan pertama, tetapi saya memberikan jawaban terbaik untuk paradoja jadi sebarkan poin sedikit tentang SO. Juga jawabannya memiliki catatan tentang versi, yang masih relevan (selama Ubuntu 8.04 saya menggunakan Ruby 1.8.6).


Seharusnya menggunakan puts "#{i} #{blah}"yang jauh lebih ringkas.

Dan Rosenstark
sumber
Tidak ada operator increment di Ruby. N + = 1 yang Anda tulis di sana adalah padanan terdekat. Ini akan menjadi gula sintaksis untuk n + = 1, yang merupakan kependekan dari n = n + 1. Ide ++ ditolak karena menyembunyikan fakta bahwa Anda sedang menugaskan ulang variabel. rubyurl.com/Dsb1
Chuck
Bagus! Terima kasih Chuck. Saya terpaksa belajar ++ i dan i ++ di Java, jadi saya pikir itu akan selalu ada.
Dan Rosenstark

Jawaban:

192

Seperti yang orang katakan, Anda bisa menggunakan

each_with_index

tetapi jika Anda ingin indeks dengan iterator berbeda dengan "each" (misalnya, jika Anda ingin memetakan dengan indeks atau semacamnya), Anda dapat menggabungkan enumerator dengan metode each_with_index, atau cukup gunakan with_index:

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

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

Ini adalah sesuatu yang dapat Anda lakukan dari ruby ​​1.8.7 dan 1.9.

paradoja
sumber
1
Perlu dicatat bahwa ini baru di 1.9.
Zach Langley
1
Terlihat bagus. Sebenarnya, ini juga di 1.8.7, tapi itu sesuatu yang layak untuk ditambahkan.
paradoja
mengapa saya menggunakan Ruby 1.8.6 jika saya baru saja menginstal semuanya di Ubuntu? Apakah 1.8.7 eksperimental / beta?
Dan Rosenstark
Ubuntu mana yang Anda gunakan? Dalam Intrepid ada 1.8.7. Ini adalah versi stabil terakhir ( ruby-lang.org/en/downloads ). Anda mungkin, bagaimanapun, monkeypatch ruby ​​1.8.6 memiliki perilaku yang sama (lihat secara ketatuntyped.com/2008/09/ruby-187s-enumerator-class.html ).
paradoja
3
Saya bosan dengan distribusi yang ketinggalan jadi saya mulai menggunakan rvm untuk mengelola instalasi Ruby saya di Ubuntu dan Linux Mint.
Manusia Timah
55
[:a, :b, :c].each_with_index do |item, i|
  puts "index: #{i}, item: #{item}"
end

Anda tidak dapat melakukan ini dengan untuk. Saya biasanya menyukai panggilan yang lebih deklaratif untuk masing-masing secara pribadi. Sebagian karena mudah untuk beralih ke bentuk lain saat Anda mencapai batas sintaks for.

Alex Wayne
sumber
Bagus, saya mengerti maksudnya tentang batasan dengan sintaks for. Saya harus terbiasa dengan blok dengan banyak parameter.
Dan Rosenstark
11

Ya, itu collection.eachuntuk melakukan loop, dan kemudian each_with_indexuntuk mendapatkan indeks.

Anda mungkin harus membaca buku Ruby karena ini adalah Ruby fundamental dan jika Anda tidak mengetahuinya, Anda akan mendapat masalah besar (coba: http://poignantguide.net/ruby/ ).

Diambil dari kode sumber Ruby:

 hash = Hash.new
 %w(cat dog wombat).each_with_index {|item, index|
   hash[item] = index
 }
 hash   #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
Matt Rogish
sumber
Tidak masalah, senang membantu. Tidak bermaksud menjadi "jahat" tentang blok .each - ini adalah konstruksi dasar ruby ​​dan mempelajarinya dengan cepat akan sangat, sangat menyakitkan. :) Terbaik untuk gigit jari dan menghabiskan beberapa jam membaca!
Matt Rogish
6

Jika Anda tidak memiliki versi baru each_with_index, Anda dapat menggunakan zipmetode untuk memasangkan indeks dengan elemen:

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

yang menghasilkan:

1 one
2 two
3 three
4 four
5 five
George
sumber
1
Di mana saya dapat menemukan kode ini dari jawaban Anda '%s %s' % [1, "two"]di dokumen Ruby? Terima kasih atas bantuan Anda dan telah menghemat ruang vertikal dengan menggunakan satu baris untuk pembuatan zipping dan pemetaan.
Dan Rosenstark
1
Dalam konteks ini, operator% -sign adalah metode kelas String. Anda dapat membacanya di ruby-doc.org/core/classes/String.html#M000770 . Atau Anda dapat mengetik ri String #% pada prompt perintah. Atau Anda dapat mengetik ri% untuk melihat semua kelas terdokumentasi yang mengenalinya, misalnya, arti yang lebih familiar di ri Fixnum #%.
George
4

Mengenai pertanyaan Anda tentang melakukan i++, Anda tidak dapat melakukannya di Ruby. The i += 1pernyataan Anda punya adalah persis bagaimana Anda seharusnya melakukannya.

paus
sumber
1

Jika blahskelas yang menggabungkan Enumerable, Anda harus dapat melakukan ini:

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

Jika Anda ingin mendapatkan indeks ruby ​​untuk masing-masing, maka Anda dapat menggunakan

.each_with_index

Berikut adalah contoh untuk menunjukkan cara .each_with_indexkerjanya:

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

Ini akan mencetak:

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
Ilyas karim
sumber