Finding the Difference Between Strings in Ruby

Finding the difference between strings in Ruby

All of the solutions so far ignore the fact that the second array can also have elements that the first array doesn't have. Chuck has pointed out a fix (see comments on other posts), but there is a more elegant solution if you work with sets:

require 'set'

teamOne = "Billy, Frankie, Stevie, John"
teamTwo = "Billy, Frankie, Stevie, Zach"

teamOneSet = teamOne.split(', ').to_set
teamTwoSet = teamTwo.split(', ').to_set

teamOneSet ^ teamTwoSet # => #<Set: {"John", "Zach"}>

This set can then be converted back to an array if need be.

comparing two strings in ruby

From what you printed, it seems var2 is an array containing one string. Or actually, it appears to hold the result of running .inspect on an array containing one string. It would be helpful to show how you are initializing them.

irb(main):005:0* v1 = "test"
=> "test"
irb(main):006:0> v2 = ["test"]
=> ["test"]
irb(main):007:0> v3 = v2.inspect
=> "[\"test\"]"
irb(main):008:0> puts v1,v2,v3
test
test
["test"]

Find the first differing character between two Strings in Ruby

Something like this ought to work:

str_a.each_char.with_index
.find_index {|char, idx| char != str_b[idx] } || str_a.size

Edit: It works: http://ideone.com/Ttwu1x

Edit 2: My original code returned nil if str_a was shorter than str_b. I've updated it to work correctly (it will return str_a.size, so if e.g. the last index in str_a is 3, it will return 4).

Here's another method that may strike some as slightly simpler:

(0...str_a.size).find {|i| str_a[i] != str_b[i] } || str_a.size

http://ideone.com/275cEU

diff a ruby string or array

diff.rb is what you want, which is available at http://users.cybercity.dk/~dsl8950/ruby/diff.html via internet archive:

http://web.archive.org/web/20140421214841/http://users.cybercity.dk:80/~dsl8950/ruby/diff.html

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 = [
[1,2,3],
[4,5,6],
[7,8,9],

[1,4,7],
[2,5,8],
[3,6,9],

[1,5,9],
[7,5,3],
]

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 = row.map { |v| board[v - 1] }
return('X') if row_values.all?('X')
return('O') if row_values.all?('O')
end

return(nil)
end

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

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

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

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

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

Comparing strings of equal lengths and noting where the differences occur

Here's where I'd start. I'm purposely using different strings to make it easier to see the differences:

str1 = 'jackdaws love my giant sphinx of quartz'
str2 = 'jackdaws l0ve my gi4nt sphinx 0f qu4rtz'

To get the first string's characters:

str1.chars.with_index.to_a - str2.chars.with_index.to_a
=> [["o", 10], ["a", 19], ["o", 30], ["a", 35]]

To get the second string's characters:

str2.chars.with_index.to_a - str1.chars.with_index.to_a
=> [["0", 10], ["4", 19], ["0", 30], ["4", 35]]

There will be a little slow down as the strings get bigger, but it won't be bad.


EDIT: Added more info.

If you have an arbitrary number of strings, and need to compare them all, use Array#combination:

str1 = 'ACCT'
str2 = 'ATCT'
str3 = 'AGCT'

require 'pp'

pp [str1, str2, str3].combination(2).to_a
>> [["ACCT", "ATCT"], ["ACCT", "AGCT"], ["ATCT", "AGCT"]]

In the above output you can see that combination cycles through the array, returning the various n sized combinations of the array elements.

pp [str1, str2, str3].combination(2).map{ |a,b| a.chars.with_index.to_a - b.chars.with_index.to_a }
>> [[["C", 1]], [["C", 1]], [["T", 1]]]

Using combination's output you could cycle through the array, comparing all the elements against each other. So, in the above returned array, in the "ACCT" and "ATCT" pair, 'C' was the difference between the two, located at position 1 in the string. Similarly, in "ACCT" and "AGCT" the difference is "C" again, in position 1. Finally for 'ATCT' and 'AGCT' it's 'T' at position 1.

Because we already saw in the longer string samples that the code will return multiple changed characters, this should get you pretty close.

What's the difference between String.new and a string literal in Ruby?

== checks for equal content.

equal? checks for equal identity.

a = "hello"
b = "hello"

a == b # => true
a.equal?(b) # => false

In Ruby string literals are not immutable and thus creating a string and using a literal are indeed the same. In both cases Ruby creates a new string instance each time the expressions in evaluated.

Both of these are thus the same

10.times { String.new }
# is the same as
10.times { "" }

Let's verify this

10.times { puts "".object_id }

Prints 10 different numbers

70227981403600
70227981403520
70227981403460
...

Why? Strings are by default mutable and thus Ruby has to create a copy each time a string literal is reached in the source code. Even if those literals are usually rarely modified in practice.

Thus a Ruby program typically creates an excessive amount short-lived string objects, which puts a huge strain on garbage collection. It is not unusual that a Rails app creates 500,000 short-lived strings just to serve one request and this is one of the main performance bottlenecks of scaling Rails to millions or even 100 millions of users.

To address that Ruby 2.3 introduced frozen string literals, where all string literals default to being immutable. Since this is not backwards compatible it is opt-in with a pragma

# frozen_string_literal: true

Let's verify this too

# frozen_string_literal: true
10.times { puts "".object_id }

Prints the same number 10 times

69898321746880
69898321746880
69898321746880
...

Fun fact, setting a key in a hash also creates a copy of a string

str = "key"
hash = {}
hash[str] = true
puts str.object_id
puts hash.keys.first.object_id

Prints two different numbers

70243164028580
70243132639660


Related Topics



Leave a reply



Submit