4

I called the following statements on a range triples = "AAA".."ZZZ":

  1. triples.include? "ABC" # => true: slow in ruby 1.9 and fast in ruby 1.8

    I understood why the output is true, but couldn't get why it's fast in ruby 1.8 and slow in ruby 1.9.

  2. triples.include? "ABCD" # => false: ruby 1.9 and true: ruby 1.8

    I couldn't get why the output is different in both versions.

  3. triples.cover? "ABCD" # => true and fast in ruby 1.9

    The same problem as the second statement.

Why are cover? and include? statements different in ruby 1.9?

Community
  • 1
  • 1
Kavish Dwivedi
  • 735
  • 6
  • 24

2 Answers2

4

In Ruby >= 1.9, include? iterates through every element in the range and checks to see if the given element is present.

cover? just checks whether the element is >= the first element range and <= the last element of the range.

Because of the way Ruby sorts strings (lexically), "ABCD" > "AAA" and "ABCD" < "ZZZ".

In Ruby 1.8, include? is treated like Ruby 1.9's cover?.

To answer your question of why they are different, your example illustrates the need for the two different methods well.

For example, if you want to check if a number is in a numeric range, (0..1_000_000_000).cover?(1_000_000_001) is much faster than include? -- checking two elements instead of a billion.

However, your example shows why include? is necessary: "ABCD" is not actually included in the range ("AAA".."ZZZ"), but it is covered by it.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
micahbf
  • 607
  • 4
  • 11
  • Ok . but what about the speed of execution that is being said about ruby 1.8 and ruby 1.9 in statemenets 1 and 3? – Kavish Dwivedi Nov 04 '13 at 07:00
  • 2
    @KavishDwivedi because the 1.9 `include?` has to iterate through all of the elements of the range (there are 26^3 of them). `cover?` just checks the first and last elements. – micahbf Nov 04 '13 at 07:02
1

In Ruby 1.9 or above, for non-numeric ranges, include? returns true only if the parameter is a member of the range.

I'd like to add that for numeric ranges, include? is still the same as cover?:

r = 1..10
r.include?(5) # => true
r.include?(5.5) # => true

Range#include?

Returns true if obj is an element of the range, false otherwise. If begin and end are numeric, comparison is done according to the magnitude of the values.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294