1

Here are two range values.

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

but,

('2'..'10').to_a  => []

Why does the second one return an empty array in ruby 1.8.7?

Inaccessible
  • 1,560
  • 3
  • 18
  • 42

4 Answers4

5

The issue is that Ruby 1.8 is trying to determine whether ('2'..'10') is a valid range as part of its analysis of the code, and deciding that it's invalid. '2' sorts after '10' making the range values backwards.

This is a common problem when people try to sort string values, and they'll encounter it again and again until they learn that trick never works.

Using 1.8.7:

('2'..'10').to_a
=> []
('02'..'10').to_a
=> ["02", "03", "04", "05", "06", "07", "08", "09", "10"]

Or:

(2..10).map(&:to_s)
=> ["2", "3", "4", "5", "6", "7", "8", "9", "10"]

I'd probably use the last method if I needed compatibility with 1.8 and 1.9+ Rubies.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
4
irb(main):001:0> '2' > '10'
=> true
irb(main):002:0> '1'>'10'
=> false

Because of the string comparison algorithm, range cannot be created with lower bound bigger than the upper bound.

ACTUALLY it works in 1.9.3. Strange.

Anton
  • 3,006
  • 3
  • 26
  • 37
  • couldn't get "range cannot be created with lower bound bigger than the upper bound". can you explain me little bit? – Inaccessible Mar 27 '13 at 13:02
  • Well, Range object is created using two objects as in `(1..5)`, 1 is the lower bound and 5 is an upper bound. Range class uses `succ` method on lower bound until it reaches the upper bound. `succ` method in string returns '10' after '9' in 1.9.3, which does not seem logical to me personally. – Anton Mar 27 '13 at 13:23
  • `succ` returns next element in an implied sequence. You don't expect that 5.succ == 4, do you? That is why `(5..1).to_a == []`. Hope you get the idea. – Anton Mar 27 '13 at 13:24
2

That's not what I'm getting:

irb(main):001:0> ('2'..'10').to_a
=> ["2", "3", "4", "5", "6", "7", "8", "9", "10"]

Unrelated to the question, though: the correct way is:

(2..10).to_a

(I am using Ruby 1.9.3)

tckmn
  • 57,719
  • 27
  • 114
  • 156
  • If you're stuck using 1.8.7 why not just convert the values to integers? `('2'.to_i..'10'.to_i).to_a` – Tom L Mar 27 '13 at 14:50
1

in ruby2.0.0-p-0 this is what I am getting :

["2", "3", "4", "5", "6", "7", "8", "9", "10"]
sunny1304
  • 1,684
  • 3
  • 17
  • 30