Ruby: String Comparison Issues

Ruby: String Comparison Issues

gets returns the entire string entered, including the newline, so when they type "M" and press enter the string you get back is "M\n". To get rid of the trailing newline, use String#chomp, i.e replace your first line with answer = gets.chomp.

String || comparison operator in Ruby

'X' || 'O' just says X or O. And since any string is truthy it always returns X. So any spot where you’ve said [('X' || 'O')], you’ve really just said ['X'].

Because of this, you’re only ever checking if a whole line of 3 is all X.

I don’t really understand how you’re trying to test this, but I feel like you’d be better off running the function twice first handing in X and then handing in O if it didn’t find X as a winner, as opposed to trying to check both as once.

Alternatively you could instead have the function return 'X', 'O', or nil and then you could have it only run the function once. The string returned would be who won and if it’s nil then no one won. I would also recommend making a loop for this. I find it easier to read.

Here's how I would solve the problem.

ROWS = [



def find_winner(board)
ROWS.each do |row|
# subtract 1 because the ROWS is 1-indexed (like a phone dial) but arrays are 0-indexed
row_values = { |v| board[v - 1] }
return('X') if row_values.all?('X')
return('O') if row_values.all?('O')


test1 = [
'X', 'X', 'X',
'O', 'X', 'O',
'O', 'O', '',
puts "Winner of test1: #{find_winner(test1).inspect}"

test2 = [
'X', '', 'X',
'X', 'O', 'O',
'X', 'O', 'X',
puts "Winner of test2: #{find_winner(test2).inspect}"

test3 = [
'O', 'X', 'X',
'O', 'X', 'O',
'O', 'O', '',
puts "Winner of test3: #{find_winner(test3).inspect}"

test4 = [
'O', 'X', 'O',
'X', 'O', 'X',
'O', 'O', 'X',
puts "Winner of test4: #{find_winner(test4).inspect}"

test5 = [
'O', 'X', 'O',
'O', 'X', 'O',
'X', 'O', 'X',
puts "Winner of test5: #{find_winner(test5).inspect}"

Ruby, problems comparing strings with UTF-8 characters

This is an issue with Unicode equivalence.

The a version of your string consists of the character ư (U+01B0: LATIN SMALL LETTER U WITH HORN), followed by U+0303 COMBINING TILDE. This second character, as the name suggests is a combining character, which when rendered is combined with the previous character to produce the final glyph.

The b version of the string uses the character (U+1EEF, LATIN SMALL LETTER U WITH HORN AND TILDE) which is a single character, and is equivalent to the previous combination, but uses a different byte sequence to represent it.

In order to compare these strings you need to normalize them, so that they both use the same byte sequences for these types of characters. Current versions of Ruby have this built in (in earlier versions you needed to use a third party library).

So currently you have

a == b

which is false, but if you do

a.unicode_normalize == b.unicode_normalize

you should get true.

If you are on an older version of Ruby, there are a couple of options. Rails has a normalize method as part of its multibyte support, so if you are using Rails you can do:

a.mb_chars.normalize == b.mb_chars.normalize

or perhaps something like:

ActiveSupport::Multibyte::Unicode.normalize(a) == ActiveSupport::Multibyte::Unicode.normalize(b)

If you’re not using Rails, then you could look at the unicode_utils gem, and do something like this:

UnicodeUtils.nfkc(a) == UnicodeUtils.nfkc(b)

(nfkc refers to the normalisation form, it is the same as the default in the other techniques.)

There are various different ways to normalise unicode strings (i.e. whether you use the decomposed or combined versions), and this example just uses the default. I’ll leave researching the differences to you.

Ruby/Rails string case comparison issue's within postgres


Food.where("lower(name) = ?", row['name'].downcase)

ruby string comparisons .match vs .eql?

As always, don't just use methods without reading their documentation. There can be important notes.

Here's eql?:

Two strings are equal if they have the same length and content.

Here's match:

Converts pattern to a Regexp (if it isn’t already one), then invokes its match method on str. If the second parameter is present, it specifies the position in the string to begin the search.

Note the part about converting. In a regular expression ( and ), among other characters, have significant meaning. You can't use match arbitrarily here. It has a very specific function.

You rarely see .eql? used in actual Ruby code, the convention is simply this:

text_from_page == error_text

The eql? method is primarily intended for internal use. It comes into play when doing comparisons, and when finding things in a container like an Array or Hash.

How do I do String comparison in Ruby?

The string returned by gets will have a linebreak at the end. Use String#chomp to remove it (i.e. state_abbreviation = gets.chomp).

PS: Your code would look much cleaner (IMHO) if you used case-when instead of if-elsif-elsif.

Is == in Ruby always value equality?

In Ruby, == can be overloaded, so it could do anything the designer of the class you're comparing wants it to do. In that respect, it's very similar to Java's equals() method.

The convention is for == to do value comparison, and most classes follow that convention, String included. So you're right, using == for comparing strings will do the expected thing.

The convention is for equal? to do reference comparison, so your test a.object_id == b.object_id could also be written a.equal?(b). (The equal? method could be defined to do something nonstandard, but then again, so can object_id!)

(Side note: when you find yourself comparing strings in Ruby, you often should have been using symbols instead.)

String comparison in Ruby

As I understand, you have two strings, s1 and s2, from which you obtain two strings:

ss1 = s1[0,n]
ss2 = s2[0,n]


n = [s1.size, s2.size].min

and you want to know if the characters of ss2 can be rearranged to equal ss1. If my understanding is correct, that would be true if and only if the following is true:

ss1.chars.sort == ss2.chars.sort


s1 = "ebcda"
s2 = "adcbefr"
n = [s1.size, s2.size].min #=> 5
ss1 = s1[0,n] #=> "ebcda"
ss2 = s2[0,n] #=> "adcbe"
ss1.chars.sort == ss2.chars.sort #=> true

Why does comparing strings in Ruby always return false?

gets will return the entered string plus a newline charcter, so you'll need to remove it. As it is a string you don't need to run to_str on the result either.

 torf = gets.downcase.chomp.eql? qs[n].answer.downcase.to_s

Related Topics

Leave a reply