402 Stimmen

Was ist der "richtige" Weg, um durch ein Array in Ruby zu iterieren?

PHP ist in dieser Hinsicht trotz all seiner Schwächen ziemlich gut. Es gibt keinen Unterschied zwischen einem Array und einem Hash (vielleicht bin ich naiv, aber das scheint mir offensichtlich richtig zu sein), und um durch beide zu iterieren, machen Sie einfach

foreach (array/hash as $key => $value)

In Ruby gibt es eine Reihe von Möglichkeiten, diese Art von Dingen zu tun:

array.length.times do |i|
end

array.each

array.each_index

for i in array

Hashes machen mehr Sinn, da ich einfach immer

hash.each do |key, value|

Warum kann ich dies nicht für Arrays tun? Wenn ich mir nur eine Methode merken möchte, kann ich wohl Folgendes verwenden each_index (da es sowohl den Index als auch den Wert verfügbar macht), aber es ist ärgerlich, wenn man die array[index] statt nur value .


Ach ja, ich vergaß array.each_with_index . Dieser hier ist jedoch scheiße, denn er geht |value, key| y hash.each geht |key, value| ! Ist das nicht wahnsinnig?

11voto

Jake Punkte 950

Hier sind die vier in Ihrer Frage genannten Optionen, geordnet nach der Freiheit der Kontrolle. Je nachdem, was Sie brauchen, sollten Sie vielleicht eine andere wählen.

  1. Gehen Sie einfach die Werte durch:

    array.each
  2. Gehen Sie einfach die Indizes durch:

    array.each_index
  3. Indizes + Indexvariable durchgehen:

    for i in array
  4. Anzahl der Regelkreise + Indexvariable:

    array.length.times do | i |

9voto

Brent.Longborough Punkte 9075

Der Versuch, dasselbe mit Arrays und Hashes zu tun puede nur ein Code Geruch sein, aber auf die Gefahr hin, dass ich als codorous Halb Affe-Patcher gebrandmarkt werden, wenn Sie für ein einheitliches Verhalten suchen, würde dies den Trick tun?

class Hash
    def each_pairwise
        self.each { | x, y |
            yield [x, y]
        }
    end
end

class Array
    def each_pairwise
        self.each_with_index { | x, y |
            yield [y, x]
        }
    end
end

["a","b","c"].each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

{"a" => "Aardvark","b" => "Bogle","c" => "Catastrophe"}.each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

5voto

Dave Everitt Punkte 15928

Ich hatte versucht, ein Menü zu erstellen (in Camping y Markaby ) unter Verwendung eines Hashes.

Jeder Artikel hat 2 Elemente: ein Menübeschriftung und eine URL Die URL "/" für "Home" erschien jedoch immer als letzte (wie man es bei einer Raute erwarten würde), so dass die Menüpunkte in der falschen Reihenfolge erschienen.

Verwendung eines Arrays mit each_slice erledigt den Job:

['Home', '/', 'Page two', 'two', 'Test', 'test'].each_slice(2) do|label,link|
   li {a label, :href => link}
end

Hinzufügen von zusätzlichen Werten für jeden Menüpunkt (z.B. wie ein CSS ID name) bedeutet lediglich, dass der Slice-Wert erhöht wird. Also, wie ein Hash, aber mit Gruppen, die aus einer beliebigen Anzahl von Elementen bestehen. Perfekt.

Ich möchte mich also dafür bedanken, dass Sie versehentlich eine Lösung angedeutet haben!

Offensichtlich, aber erwähnenswert: Ich schlage vor zu prüfen, ob die Länge des Arrays durch den Slice-Wert teilbar ist.

4voto

maxhawkins Punkte 828

Wenn Sie die aufzählbar mixin (wie Rails es tut) können Sie etwas ähnliches wie das php-Snippet aufgeführt tun. Verwenden Sie einfach die Methode each_slice und glätten Sie den Hash.

require 'enumerator' 

['a',1,'b',2].to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

# is equivalent to...

{'a'=>1,'b'=>2}.to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

Weniger monkey-Parcheando erforderlich.

Dies führt jedoch zu Problemen, wenn Sie ein rekursives Array oder einen Hash mit Array-Werten haben. In Ruby 1.9 wurde dieses Problem mit einem Parameter für die flatten-Methode gelöst, der angibt, wie tief rekursiert werden soll.

# Ruby 1.8
[1,2,[1,2,3]].flatten
=> [1,2,1,2,3]

# Ruby 1.9
[1,2,[1,2,3]].flatten(0)
=> [1,2,[1,2,3]]

Was die Frage betrifft, ob es sich um einen Codegeruch handelt, bin ich mir nicht sicher. Normalerweise, wenn ich zu beugen haben über etwas zu iterieren ich Schritt zurück und erkennen, ich bin das Problem falsch angegangen.

3voto

Amjed Shareef Punkte 73

In Ruby 2.1 wurde die Methode each_with_index entfernt. Stattdessen können Sie verwenden jeder_index

Beispiel:

a = [ "a", "b", "c" ]
a.each_index {|x| print x, " -- " }

produziert:

0 -- 1 -- 2 --

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X