Modo corretto di popolare una matrice con un intervallo in Ruby


201

Sto lavorando a un libro che fornisce esempi di Ranges convertiti in array equivalenti usando i loro metodi "to_a"

Quando eseguo il codice in IRB ricevo il seguente avviso

 warning: default `to_a' will be obsolete

Qual è l'alternativa corretta all'utilizzo di to_a?

ci sono modi alternativi per popolare un array con un intervallo?


7
Il grande avvertimento per la conversione di un intervallo in un array, è che un ampio intervallo può consumare molta memoria quando l'array viene creato, quindi usalo con cura. Invece di creare l'array, potrebbe essere meglio iterare sull'intervallo come se fosse un array per ridurre il consumo di memoria. È una di quelle cose da "applicare se necessario".
Tin Man,

Risposte:


357

Puoi creare un array con un intervallo usando splat,

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

usando il Kernel Arraymetodo,

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

o usando to_a

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

1
Che cosa succede se l'array è già stato creato e si desidera aggiungere un intervallo ad esso: ho order = 1. Poi order << (2.25).to_a. Ma questo crea un altro array all'interno dell'array, voglio semplicemente l'intervallo da 2 a 25. Tuttavia, se provo, order << (2.25)ottengo l'errore non posso convertire Range in Integer.
kakubei,

1
@kakubei usa concatinvece di <<. Inoltre, non dovresti ottenere "Impossibile convertire l'intervallo in intero" a meno che non ordersia un intero - nel qual caso dovresti spostare i bit, non aggiungere la matrice.
Kelvin,

3
l'opzione Splat non funziona per Ruby 1.8.7, consiglierei di utilizzare (1..10).to_aper la compatibilità con le versioni precedenti
kylewelsby

5
L'uso di splat è brutto. L'opzione migliore è [*1..10].
Hauleth,

2
qual è il modo più veloce ??
Andrey Yasinishyn,

79

Questo funziona per me in Irlanda:

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

L'ho notato:

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

Quindi forse ti mancano le parentesi?

(Sto eseguendo Ruby 1.8.6 patchlevel 114)


7
Spiegazione : senza parentesi, si chiama il metodo to_a da un'istanza della classe Fixnum (in questo caso 4), non nell'intervallo 1..4. Se esegui Fixnum.methods.include?(to_a)ruby 1.9.2 noterai che il metodo to_a non è più definito, quindi perché hai ricevuto quel messaggio di deprezzamento in 08
Pierre,

@Pierre Penso che volevi direFixnum.instance_methods.include?(:to_a)
Kelvin

@Kelvin - In realtà, methods.include?è più informativo: $ irb irb(main):001:0> Fixnum.methods.include?(to_a) (irb):1: warning: default to_a 'sarà obsoleto=> false irb(main):002:0> Fixnum.instance_methods.include?(:to_a) => false
Richard Turner,

1
@RichardTurner Presumo che tu stia usando ruby ​​1.8. Temo che tu abbia frainteso ciò che innesca l' to_aavvertimento nella prima forma. È perché si sta chiamando to_asul self- non sono in realtà verificare se to_aè un metodo di Fixnum. Prova a chiamare to_ada solo e vedrai lo stesso avviso.
Kelvin,

@Kelvin - Duh! Il penny scende. Grazie.
Richard Turner,

34

Sembra che tu stia facendo questo:

0..10.to_a

L'avvertimento proviene da Fixnum # to_a, non da Range # a_a. Prova questo invece:

(0..10).to_a

9

Controllare questo:

a = [*(1..10), :top, *10.downto( 1 )]

2
* 10.downto (1) era quello che stavo cercando, grazie!
Daniel,


4

Ho appena provato a utilizzare intervalli da quantità maggiori a minori e ho ottenuto il risultato che non mi aspettavo:

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

Ciò è dovuto alle implementazioni di intervalli.
Quindi ho dovuto usare la seguente opzione:

(1..5).to_a.reverse

4
Oggi ho scoperto 5.downto(1).to_ache è un altro modo di esprimere una gamma diminuzione stackoverflow.com/a/8927009/703903
odlp
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.