Richtige Methode zum Auffüllen eines Arrays mit einem Bereich in Ruby

201

Ich arbeite an einem Buch, das Beispiele für Bereiche enthält, die mit ihren "to_a" -Methoden in äquivalente Arrays konvertiert werden

Wenn ich den Code in irb ausführe, erhalte ich die folgende Warnung

 warning: default `to_a' will be obsolete

Was ist die richtige Alternative zur Verwendung von to_a?

Gibt es alternative Möglichkeiten, ein Array mit einem Bereich zu füllen?

Willbill
quelle
7
Die große Einschränkung beim Konvertieren eines Bereichs in ein Array besteht darin, dass ein großer Bereich beim Erstellen des Arrays viel Speicherplatz beanspruchen kann. Gehen Sie daher vorsichtig damit um. Anstatt das Array zu erstellen, ist es möglicherweise besser, über den Bereich zu iterieren, als würden Sie ein Array verwenden, um den Speicherverbrauch niedrig zu halten. Es ist eines dieser Dinge, die "nach Bedarf anwenden".
der Blechmann

Antworten:

357

Sie können ein Array mit einem Bereich mit splat erstellen.

>> a=*(1..10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

mit Kernel ArrayMethode,

Array (1..10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

oder mit to_a

(1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Zamith
quelle
1
Was ist, wenn das Array bereits erstellt wurde und Sie einen Bereich hinzufügen möchten: Ich habe order = 1. Dann order << (2.25).to_a. Dies erzeugt jedoch ein anderes Array innerhalb des Arrays. Ich möchte einfach den Bereich von 2 bis 25. Wenn ich jedoch versuche order << (2.25), den Fehler zu erhalten, kann Range nicht in Integer konvertiert werden.
Kakubei
1
@ kakubei verwenden concatstatt <<. Außerdem sollten Sie nicht "kann Range nicht in Integer konvertieren" erhalten, es ordersei denn, es handelt sich um eine Ganzzahl. In diesem Fall würden Sie Bitverschiebungen vornehmen und keine Arrays anhängen.
Kelvin
3
die Splat Option für Ruby nicht funktioniert 1.8.7, würde ich mit empfehlen (1..10).to_afür die Abwärtskompatibilität
kylewelsby
5
Ihre Verwendung von Splat ist böse. Besser aussehende Option ist [*1..10].
Hauleth
2
Was ist der schnellste Weg?
Andrey Yasinishyn
79

Das funktioniert bei mir in irb:

irb> (1..4).to_a
=> [1, 2, 3, 4]

Ich bemerke das:

irb> 1..4.to_a
(irb):1: warning: default `to_a' will be obsolete
ArgumentError: bad value for range
        from (irb):1

Vielleicht fehlen Ihnen die Klammern?

(Ich verwende Ruby 1.8.6 Patchlevel 114)

Daniel Lucraft
quelle
7
Erläuterung : Ohne die Klammer rufen Sie die Methode to_a von einer Instanz der Fixnum-Klasse (in diesem Fall 4) auf, nicht im Bereich 1..4. Wenn Sie Fixnum.methods.include?(to_a)in Ruby 1.9.2 laufen, werden Sie feststellen, dass die to_a-Methode nicht mehr definiert ist, weshalb Sie diese Abschreibungsnachricht in 08
Pierre
@ Pierre Ich denke du meintestFixnum.instance_methods.include?(:to_a)
Kelvin
@ Kelvin - Eigentlich methods.include?ist informativer: $ irb irb(main):001:0> Fixnum.methods.include?(to_a) (irb):1: warning: default to_a 'wird veraltet sein=> false irb(main):002:0> Fixnum.instance_methods.include?(:to_a) => false
Richard Turner
1
@ RichardTurner Ich nehme an, Sie verwenden Ruby 1.8. Ich fürchte, Sie verstehen falsch, was die to_aWarnung in der ersten Form auslöst . Es ist , weil Sie anrufen to_aauf self- Sie sind nicht wirklich zu prüfen , ob to_aein Verfahren der Fixnum ist. Wenn to_aSie versuchen, selbst anzurufen, wird dieselbe Warnung angezeigt.
Kelvin
@ Kelvin - Duh! Der Penny fällt. Vielen Dank.
Richard Turner
34

Klingt so, als ob Sie dies tun:

0..10.to_a

Die Warnung stammt von Fixnum # to_a, nicht von Range # to_a. Versuchen Sie stattdessen Folgendes:

(0..10).to_a
Richard Turner
quelle
9

Überprüfen Sie dies:

a = [*(1..10), :top, *10.downto( 1 )]
Boris Stitnicky
quelle
2
Der * 10.downto (1) war das, wonach ich gesucht habe, danke!
Daniel
6

Dies ist ein anderer Weg:

irb> [*1..10]

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Jesús Andrés Valencia Montoya
quelle
4

Ich habe nur versucht, Bereiche von größerer bis kleinerer Menge zu verwenden und habe das Ergebnis erhalten, das ich nicht erwartet hatte:

irb(main):007:0> Array(1..5)
=> [1, 2, 3, 4, 5]
irb(main):008:0> Array(5..1)
=> []

Das liegt an Bereichsimplementierungen.
Also musste ich folgende Option verwenden:

(1..5).to_a.reverse
Nickolay Kondratenko
quelle
4
Heute habe ich herausgefunden, 5.downto(1).to_awas eine andere Möglichkeit ist, einen abnehmenden Bereich auszudrücken. Stackoverflow.com/a/8927009/703903
odlp