224

I am working through a book which gives examples of Ranges being converted to equivalent arrays using their "to_a" methods

When i run the code in irb I get the following warning

 warning: default `to_a' will be obsolete

What is the the correct alternative to using to_a?

are there alternate ways to populate an array with a Range?

dax
  • 10,779
  • 8
  • 51
  • 86
Willbill
  • 4,673
  • 6
  • 24
  • 25
  • 9
    The big caveat to converting a range to an array, is a big range can consume a lot of memory when the array is built, so use it with care. Instead of creating the array, it might be better to iterate over the range like you would an array to keep the memory consumption down. It's one of those "apply as necessary" things. – the Tin Man Jul 05 '11 at 22:11

6 Answers6

399

You can create an array with a range using splat,

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

using Kernel Array method,

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

or using to_a

(1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Waiting for Dev...
  • 12,629
  • 5
  • 47
  • 57
Zamith
  • 22,900
  • 2
  • 24
  • 16
  • 1
    What if the array is already created and you want to add a range to it: I have `order = 1`. Then `order << (2.25).to_a`. But this creates another array inside the array, I simply want the range from 2 to 25. Yet if I try `order << (2.25)` I get the error can't convert Range into Integer. – kakubei Nov 10 '11 at 14:29
  • 1
    @kakubei use `concat` instead of `<<`. Also, you shouldn't be getting "can't convert Range into Integer" unless `order` is an integer - in which case you'd be bit-shifting, not array-appending. – Kelvin Jan 17 '12 at 21:12
  • 3
    the Splat option doesn't work for Ruby 1.8.7, I would recommend using `(1..10).to_a` for backwards compatibility – kylewelsby Mar 06 '13 at 19:25
  • 9
    Your usage of splat is nasty. Better looking option is `[*1..10]`. – Hauleth May 18 '13 at 20:36
  • 2
    I use splat in a way it can also be used with variables, so it can be used as a=*range, it's more consistent. But that's a matter of taste. – Zamith Jun 06 '13 at 11:45
  • 2
    what is the fastest way?? – Andrey Yasinishyn Aug 14 '13 at 07:34
  • Contra @halfcube, the splat example is working for me, some years down the road, on ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux], ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]. – Martin Dorey Aug 26 '15 at 22:59
83

This works for me in irb:

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

I notice that:

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

So perhaps you are missing the parentheses?

(I am running Ruby 1.8.6 patchlevel 114)

Daniel Lucraft
  • 7,196
  • 6
  • 34
  • 35
  • 8
    **Explanation**: without the parenthesis, you're calling the to_a method from an instance of the Fixnum Class (in this case 4), not on the range 1..4. If you run `Fixnum.methods.include?(to_a)` in ruby 1.9.2 you'll notice that the to_a method is no longer defined, hence why you were getting that depreciation message in 08 – Pierre Oct 21 '11 at 17:23
  • @Pierre I think you meant `Fixnum.instance_methods.include?(:to_a)` – Kelvin Jan 17 '12 at 21:08
  • @Kelvin - Actually, `methods.include?` is more informative: `$ irb` `irb(main):001:0> Fixnum.methods.include?(to_a)` `(irb):1: warning: default `to_a' will be obsolete `=> false` `irb(main):002:0> Fixnum.instance_methods.include?(:to_a)` `=> false` – Richard Turner Jan 19 '12 at 11:48
  • 1
    @RichardTurner I assume you're using ruby 1.8. I'm afraid you're misunderstanding what's triggering the `to_a` warning in the first form. It's because you're calling `to_a` on `self` - you are not actually checking whether `to_a` is a method of Fixnum. Try calling `to_a` by itself and you'll see the same warning. – Kelvin Jan 19 '12 at 16:23
  • @Kelvin - Duh! The penny drops. Thanks. – Richard Turner Jan 19 '12 at 22:25
36

Sounds like you're doing this:

0..10.to_a

The warning is from Fixnum#to_a, not from Range#to_a. Try this instead:

(0..10).to_a
Richard Turner
  • 12,506
  • 6
  • 36
  • 37
10

Check this:

a = [*(1..10), :top, *10.downto( 1 )]
Boris Stitnicky
  • 12,444
  • 5
  • 57
  • 74
9

This is another way:

irb> [*1..10]

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Sam
  • 5,997
  • 5
  • 46
  • 66
5

I just tried to use ranges from bigger to smaller amount and got the result I didn't expect:

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

That's because of ranges implementations.
So I had to use the following option:

(1..5).to_a.reverse
Nickolay Kondratenko
  • 1,871
  • 2
  • 21
  • 25
  • 4
    Today I discovered `5.downto(1).to_a` which is another way of expressing a decreasing range https://stackoverflow.com/a/8927009/703903 – odlp Jun 30 '17 at 10:19