Automatischer Zähler in Ruby für jeden?

134

Ich möchte einen für jeden und einen Zähler verwenden:

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

Gibt es einen besseren Weg, dies zu tun?

Hinweis: Ich weiß nicht, ob blahses sich um ein Array oder einen Hash handelt, aber wenn ich es tun muss, wird blahs[i]es nicht viel sexy. Außerdem würde ich gerne wissen, wie man i++in Ruby schreibt .


Technisch gesehen kam die Antwort von Matt und Squeegy zuerst, aber ich gebe Paradoja die beste Antwort, also verteile mich ein bisschen auf SO. Auch seine Antwort hatte den Hinweis zu Versionen, der immer noch relevant ist (solange mein Ubuntu 8.04 Ruby 1.8.6 verwendet).


Hätte verwenden sollen, puts "#{i} #{blah}"was viel prägnanter ist.

Dan Rosenstark
quelle
In Ruby gibt es keinen Inkrementoperator. Das n + = 1, das Sie dort geschrieben haben, ist das nächste Äquivalent. Es müsste syntaktischer Zucker für n + = 1 sein, was selbst eine Abkürzung für n = n + 1 ist. Die Idee von ++ wurde abgelehnt, weil sie die Tatsache verbirgt, dass Sie die Variable neu zuweisen. rubyurl.com/Dsb1
Chuck
Nett! Danke Chuck. Ich war gezwungen, ++ i und i ++ in Java zu lernen, also dachte ich nur, dass es immer da sein würde.
Dan Rosenstark

Antworten:

190

Wie die Leute gesagt haben, können Sie verwenden

each_with_index

Wenn Sie jedoch Indizes mit einem anderen Iterator als "jeder" möchten (z. B. wenn Sie einen Index oder ähnliches zuordnen möchten), können Sie Enumeratoren mit der Methode each_with_index verketten oder einfach with_index verwenden:

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

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

Dies können Sie mit Ruby 1.8.7 und 1.9 tun.

paradoja
quelle
1
Es ist erwähnenswert, dass dies in 1.9 neu ist.
Zach Langley
1
Gut erkannt. Eigentlich ist es auch in 1.8.7, aber es lohnt sich hinzuzufügen.
Paradoja
Warum bin ich auf Ruby 1.8.6, wenn ich das Ganze nur auf Ubuntu installiert habe? Ist 1.8.7 experimentell / Beta?
Dan Rosenstark
Welches Ubuntu benutzt du? In Intrepid gibt es 1.8.7. Es ist die letzte stabile Version ( ruby-lang.org/en/downloads ). Sie können jedoch monkeypatch Rubin 1.8.6 das gleiche Verhalten haben (siehe strictlyuntyped.com/2008/09/ruby-187s-enumerator-class.html ).
Paradoja
3
Ich hatte es satt, dass die Distribution dahinter steckt, und begann, meine Ruby-Installation unter Ubuntu und Linux Mint mit rvm zu verwalten.
der Blechmann
55
[:a, :b, :c].each_with_index do |item, i|
  puts "index: #{i}, item: #{item}"
end

Sie können dies nicht mit für tun. Normalerweise mag ich den deklarativeren Anruf an jeden persönlich sowieso. Zum Teil, weil es einfach ist, zu anderen Formen zu wechseln, wenn Sie die Grenze der for-Syntax erreichen.

Alex Wayne
quelle
Schön, ich sehe den Punkt über die Grenzen mit der for-Syntax. Ich muss mich an Blöcke mit mehreren Parametern gewöhnen.
Dan Rosenstark
11

Ja, es geht collection.eachdarum, Schleifen zu machen und dann each_with_indexden Index zu erhalten.

Sie sollten wahrscheinlich ein Ruby-Buch lesen, da dies ein grundlegender Ruby ist und wenn Sie es nicht wissen, werden Sie in große Schwierigkeiten geraten (versuchen Sie: http://poignantguide.net/ruby/ ).

Entnommen aus dem Ruby-Quellcode:

 hash = Hash.new
 %w(cat dog wombat).each_with_index {|item, index|
   hash[item] = index
 }
 hash   #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
Matt Rogish
quelle
Kein Problem, gerne helfen. Wollte nicht "gemein" über den .each-Block sein - dies sind grundlegende Rubinkonstrukte, und es wird sehr, sehr schmerzhaft sein, sie im laufenden Betrieb zu lernen. :) Am besten in die Kugel beißen und ein paar Stunden lesen!
Matt Rogish
6

Wenn Sie nicht über die neue Version von verfügen each_with_index, können Sie die zipMethode verwenden, um Indizes mit Elementen zu koppeln:

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

welches produziert:

1 one
2 two
3 three
4 four
5 five
George
quelle
1
Wo finde ich diesen Code aus Ihrer Antwort '%s %s' % [1, "two"]in den Ruby-Dokumenten? Vielen Dank für Ihre Hilfe und für die Schonung des vertikalen Platzes, indem Sie eine Linie zum Zippen und Mappen verwenden.
Dan Rosenstark
1
In diesem Zusammenhang ist der Operator% -sign eine Methode der String-Klasse. Sie können darüber unter ruby-doc.org/core/classes/String.html#M000770 lesen . Oder Sie können an einer Eingabeaufforderung ri String #% eingeben. Oder Sie können ri% eingeben, um alle dokumentierten Klassen anzuzeigen, die es erkennen, z. B. die bekanntere Bedeutung bei ri Fixnum #%.
George
4

Was Ihre Frage betrifft i++, können Sie dies in Ruby nicht tun. Die i += 1Aussage, die Sie hatten, ist genau so, wie Sie es tun sollen.

Papst
quelle
1

Wenn blahses sich um eine Klasse handelt, die Enumerable mischt, sollten Sie in der Lage sein, Folgendes zu tun:

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

Wenn Sie für jeden einen Rubinindex erhalten möchten, können Sie diesen verwenden

.each_with_index

Hier ist ein Beispiel, um zu zeigen, wie es .each_with_indexfunktioniert:

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

Dies wird gedruckt:

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
quelle