2012-06-11 6 views
5

Angenommen, ich habe ein aufzählbares Objekt enum und jetzt möchte ich das dritte Element erhalten.verweisen einen Enumerator-Wert mit angegebenen Index

Ich kenne einer von einem allgemeinen Ansatz wird in ein Array umwandeln und Zugriff dann mit dem Index wie:

enum.to_a[2] 

Aber diese Art und Weise wird eine temporäre Array erstellen und es könnte ineffizient sein.

Jetzt benutze ich:

enum.each_with_index {|v, i| break v if i == 2} 

Aber das ist ziemlich hässlich und redundant.

Was ist der effizienteste Weg, dies zu tun?

Antwort

5

Sie könnten take verwenden die ersten drei Elemente zu schälen und dann last das dritte Element aus dem Array zu greifen, dass take gibt Ihnen:

third = enum.take(3).last 

Wenn Sie nicht wollen, überhaupt keine Arrays zu erzeugen, dann vielleicht:

# If enum isn't an Enumerator then 'enum = enum.to_enum' or 'enum = enum.each' 
# to make it one. 
(3 - 1).times { enum.next } 
third = enum.next 
+0

Das sieht besser aus, aber wenn ich eine sehr große Zahl als Index will, wird es immer noch eine sehr große temporäre Array für sie generiert. –

+0

@ShouYa: Ich habe während des Kommentars eine andere Array-lose Option hinzugefügt. Sie müssen noch nacheinander "Enum" durchgehen, aber Sie können nichts dagegen tun (im Allgemeinen). –

+0

Mit Next ist ein kluger Vorschlag. Ich wäre neugierig zu sehen, was die Implikationen der Performance im Vergleich zur Umwandlung einer Sammlung in ein Array sind. –

1

Leider auf ein Mitglied zugreifen, indem Sie indizieren in ein Array umgewandelt werden muss (sonst würden Sie nicht einen Index in den ersten Platz haben), so sieht der Code völlig in Ordnung für mich.

+0

Um, nein. Wenn 'e' ein' Enumerator' ist, dann wird '2.x {e.next}' abhaken und die ersten beiden Werte wegwerfen und ein drittes 'e.next' wird dir den dritten geben, ohne irgendwelche Arrays zu erzeugen. –

+0

@muistooshort yep, antwortete ich auf deinen Thread. Und Sie haben Recht. –

5

Alternative zu Muis Antwort mit enumerable-lazy oder Ruby 2.1. So faul wie next verwenden, aber viel mehr deklarative:

enum.lazy.drop(2).first