Forma correcta de poblar una matriz con un rango en Ruby

201

Estoy trabajando en un libro que da ejemplos de rangos que se convierten en matrices equivalentes utilizando sus métodos "to_a"

Cuando ejecuto el código en irb me sale la siguiente advertencia

 warning: default `to_a' will be obsolete

¿Cuál es la alternativa correcta al uso de to_a?

¿Hay formas alternativas de llenar una matriz con un rango?

Willbill
fuente
77
La gran advertencia para convertir un rango en una matriz es que un gran rango puede consumir mucha memoria cuando se construye la matriz, así que úselo con cuidado. En lugar de crear la matriz, podría ser mejor iterar sobre el rango como lo haría con una matriz para mantener bajo el consumo de memoria. Es una de esas cosas de "aplicar según sea necesario".
The Tin Man

Respuestas:

357

Puede crear una matriz con un rango usando splat,

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

utilizando el Kernel Arraymétodo,

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]
Zamith
fuente
1
¿Qué pasa si la matriz ya está creada y desea agregarle un rango order = 1? Entonces order << (2.25).to_a. Pero esto crea otra matriz dentro de la matriz, simplemente quiero el rango de 2 a 25. Sin embargo, si lo intento order << (2.25), obtengo el error no puede convertir el rango en entero.
kakubei
1
@kakubei uso en concatlugar de <<. Además, no debería estar obteniendo "no se puede convertir el rango en entero" a menos que ordersea ​​un entero, en cuyo caso estaría cambiando de bit, no agregando matriz.
Kelvin
3
la opción Splat no funciona para Ruby 1.8.7, recomendaría usar (1..10).to_apara compatibilidad con versiones anteriores
kylewelsby
55
Su uso de splat es desagradable. La mejor opción es [*1..10].
Hauleth
2
¿Cuál es la forma más rápida?
Andrey Yasinishyn
79

Esto funciona para mí en irb:

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

Me doy cuenta de que:

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

¿Entonces quizás te estás perdiendo los paréntesis?

(Estoy ejecutando Ruby 1.8.6 patchlevel 114)

Daniel Lucraft
fuente
77
Explicación : sin el paréntesis, está llamando al método to_a desde una instancia de la clase Fixnum (en este caso 4), no en el rango 1..4. Si ejecuta Fixnum.methods.include?(to_a)en ruby ​​1.9.2, notará que el método to_a ya no está definido, de ahí que recibiera ese mensaje de depreciación en 08
Pierre
@Pierre Creo que quisiste decirFixnum.instance_methods.include?(:to_a)
Kelvin
@Kelvin - En realidad, methods.include?es más informativo: $ irb irb(main):001:0> Fixnum.methods.include?(to_a) (irb):1: warning: default to_a 'será obsoleto=> false irb(main):002:0> Fixnum.instance_methods.include?(:to_a) => false
Richard Turner
1
@ RichardTurner Supongo que estás usando Ruby 1.8. Me temo que estás malinterpretando lo que desencadena la to_aadvertencia en la primera forma. Es porque está llamando, to_aen selfrealidad no está verificando si to_aes un método de Fixnum. Intenta llamar to_asolo y verás la misma advertencia.
Kelvin
@Kelvin - Duh! El centavo cae. Gracias.
Richard Turner
34

Parece que estás haciendo esto:

0..10.to_a

La advertencia es de Fixnum # to_a, no de Range # to_a. Intenta esto en su lugar:

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

Mira esto:

a = [*(1..10), :top, *10.downto( 1 )]
Boris Stitnicky
fuente
2
El * 10.downto (1) era lo que estaba buscando, ¡gracias!
Daniel
6

Esta es otra forma:

irb> [*1..10]

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

Solo intenté usar rangos de mayor a menor cantidad y obtuve el resultado que no esperaba:

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

Eso se debe a las implementaciones de rangos.
Entonces tuve que usar la siguiente opción:

(1..5).to_a.reverse
Nickolay Kondratenko
fuente
44
Hoy descubrí 5.downto(1).to_acuál es otra forma de expresar un rango decreciente stackoverflow.com/a/8927009/703903
odlp