Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

205
Visualizações
Why is the string '3' not matched in a case statement with the range ('0'...'10')?

When I try to match for the string '3' in a case statement, it matches if the range goes up to '9', but not '10'.

I'm guessing it has something to do with the triple equals operator, but I don't know the exact reason why it can be in the range, but not matched.

Here is an IRB run documenting both cases that work (with '9'), and don't work (with '10'):

 case '3'
 when ('0'...'9')
     puts "number is valid"
 else
   puts "number is not valid"
 end

Output: number is valid

 case '3'
 when ('0'...'10')
     puts "number is valid"
 else
   puts "number is not valid"
 end

Output: number is not valid

The methods that I used as a reference for the expected results are
Enumerable#include?
Enumerable#member?
and seeing what is output when converted to an array is (Enumerable#to_a).

The result of the "case equality" (===) operator surprised me.

 puts ('0'...'10').include?('3')
 # => true
 puts ('0'...'10').member?('3')
 # => true
 puts ('0'...'10') === '3'
 # => false
 puts ('0'...'10').to_a
 # => ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

=== says it's equivalent to cover?, and the documentation for the latter states that it's equivalent to

begin <= obj < end

So, in your case, we're getting

'0' <= '3' < '10'

And <= and < on strings compare using dictionary order, so the comparison is false.

On the other hand, we have to do a bit more digging to figure out what member? / include? actually do (the two are equivalent). If we look in the source code, we see that both invoke a function called range_include_internal which has a special case for string arguments that behaves differently than cover?. The latter calls rb_str_include_range_p which has even more special cases, including your digit case.

over 4 years ago · Santiago Trujillo Relatório

0

Ranges use cover? for case equality. So it is comparing '3' >= '0' && '3' < '10' which results in false because '3' < '10' #=> false. Strings are compared based on character values.

For a better understanding you might want to see a string as an array of characters:

['3'] <=> ['1', '0'] #=> 1 (first operand is larger than the second)

To solve the issue convert your case input to an integer and use integer ranges:

case 3 # or variable.to_i
when 0...10
  puts 'number is valid'
else
  puts 'number is invalid'
end

This works because integers are not compared based on character code, but on actual value. 3 >= 0 && 3 < 10 results in true.

Alternatively you could explicitly tell when to use the member? (or include?) method, by not passing a range, but a method instead.

case '3'
when ('0'...'10').method(:member?)
  puts 'number is valid'
else
  puts 'number is invalid'
end
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda