Automatyczny licznik w Rubim dla każdego?


134

Chcę użyć for-each i counter:

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

Czy jest lepszy sposób, aby to zrobić?

Uwaga: nie wiem, czy blahsto tablica, czy hash, ale konieczność zrobienia blahs[i]tego nie uczyniłaby tego bardziej seksownym. Chciałbym również wiedzieć, jak pisać i++w języku Ruby.


Technicznie rzecz biorąc, odpowiedź Matta i Squeegy'ego była pierwsza, ale ja daję najlepszą odpowiedź na paradoję, więc rozprowadź trochę punkty na SO. Jego odpowiedź zawierała również notatkę o wersjach, która jest nadal aktualna (o ile mój Ubuntu 8.04 używa Ruby 1.8.6).


Powinienem był użyć, puts "#{i} #{blah}"który jest o wiele bardziej zwięzły.


W Rubim nie ma operatora przyrostu. Zapisane tam n + = 1 jest najbliższym odpowiednikiem. Musiałby to być cukier syntaktyczny dla n + = 1, co samo w sobie jest skrótem dla n = n + 1. Pomysł ++ został odrzucony, ponieważ ukrywa fakt, że ponownie przypisujesz zmienną. rubyurl.com/Dsb1
Chuck,

Miły! Dzięki, Chuck. Byłem zmuszony nauczyć się ++ i i i ++ w Javie, więc pomyślałem, że zawsze tam będzie.
Dan Rosenstark

Odpowiedzi:


190

Jak powiedzieli ludzie, możesz użyć

each_with_index

ale jeśli potrzebujesz indeksów z iteratorem innym niż "each" (na przykład, jeśli chcesz mapować z indeksem lub czymś podobnym), możesz połączyć wyliczające z metodą each_with_index lub po prostu użyć with_index:

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

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

To jest coś, co możesz zrobić w Ruby 1.8.7 i 1.9.


1
Warto zauważyć, że jest to nowość w 1.9.
Zach Langley,

1
Dobrze zauważony. Właściwie to też jest w 1.8.7, ale warto to dodać.
paradoja

dlaczego jestem na Rubim 1.8.6, skoro właśnie zainstalowałem całość na Ubuntu? Czy 1.8.7 jest eksperymentalny / beta?
Dan Rosenstark

Którego Ubuntu używasz? W Intrepid jest 1.8.7. To ostatnia stabilna wersja ( ruby-lang.org/en/downloads ). Możesz jednak, monkeypatch ruby ​​1.8.6, mieć takie samo zachowanie (patrz strictlyuntyped.com/2008/09/ruby-187s-enumerator-class.html ).
paradoja

3
Zmęczyło mnie to, że dystrybucja jest w tyle, więc zacząłem używać rvm do zarządzania moją instalacją Ruby na Ubuntu i Linux Mint.
Tin Man,

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

Nie możesz tego zrobić za. I tak zwykle lubię bardziej deklaratywne wezwanie do każdego osobiście. Częściowo dlatego, że łatwo jest przejść do innych form, gdy osiągniesz granicę składni for.


Świetnie, rozumiem granice w składni for. Muszę się przyzwyczaić do bloków z wieloma parametrami.
Dan Rosenstark

11

Tak, to collection.eachzrobić pętle, a następnie each_with_indexuzyskać indeks.

Prawdopodobnie powinieneś przeczytać książkę o Rubim, ponieważ jest to fundamentalna wersja Rubiego i jeśli jej nie znasz, będziesz miał duże kłopoty (spróbuj: http://poignantguide.net/ruby/ ).

Zaczerpnięte z kodu źródłowego Rubiego:

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

Nie ma problemu, chętnie pomogę. Nie chciałem być „wredny” w stosunku do bloku .each - to są fundamentalne konstrukcje rubinowe i nauka ich w locie będzie naprawdę, bardzo bolesna. :) Najlepiej ugryźć kulę i poświęcić kilka godzin na czytanie!
Matt Rogish,

6

Jeśli nie masz nowej wersji each_with_index, możesz użyć zipmetody do parowania indeksów z elementami:

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

który produkuje:

1 one
2 two
3 three
4 four
5 five

1
Gdzie mogę znaleźć ten kod z Twojej odpowiedzi '%s %s' % [1, "two"]w dokumentach Rubiego? Dziękujemy za pomoc i zaoszczędzenie miejsca w pionie przez użycie jednej linii do spakowania i mapowania.
Dan Rosenstark

1
W tym kontekście operator% -sign jest metodą klasy String. Możesz o tym przeczytać na ruby-doc.org/core/classes/String.html#M000770 . Lub możesz wpisać ri String #% w wierszu polecenia. Lub możesz wpisać ri%, aby zobaczyć wszystkie udokumentowane klasy, które go rozpoznają, np. Bardziej znane znaczenie w ri Fixnum #%.
George

4

Co do twojego pytania o robienie i++, cóż, nie możesz tego zrobić w Rubim. i += 1Oświadczenie trzeba było to dokładnie w jaki sposób powinniśmy to zrobić.



1

Jeśli blahsjest to klasa, która miesza się w Enumerable, powinieneś móc to zrobić:

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

1

Jeśli chcesz uzyskać indeks rubinów dla każdego z nich, możesz użyć

.each_with_index

Oto przykład pokazujący, jak to .each_with_indexdziała:

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

Spowoduje to wydrukowanie:

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.