15

I need to take two strings, compare them, and print the difference between them.

So say I have:

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

$ teamOne.eql? teamTwo 
=> false

I want to say "If the two strings are not equal, print whatever it is that is different between them. In this case, I'm just looking to print "John."

Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
btw
  • 7,006
  • 9
  • 40
  • 40
  • 1
    Seems like a duplicate of http://stackoverflow.com/questions/80091/diff-a-ruby-string-or-array – Samuel Jan 08 '09 at 22:17
  • see this http://stackoverflow.com/questions/13824444/comparing-two-strings-in-ruby/13824648#13824648 – tokhi Jan 06 '16 at 14:52

5 Answers5

20

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.

Zach Langley
  • 6,776
  • 1
  • 26
  • 25
  • 2
    This solution fails when there is a repetitive item in one string, example .. teamOne = "Billy, Frankie, Stevie, John, Billy" . Not in the set one Billy will be removed ..cuz you know it's a set, now intersection of two sets won't give you the result as it should – Vamsi Pavan Mahesh Apr 04 '17 at 12:14
5

If the real string you are comparing are similar to the strings you provided, then this should work:

teamOneArr = teamOne.split(", ")
=> ["Billy", "Frankie", Stevie", "John"]
teamTwoArr = teamTwo.split(", ")
=> ["Billy", "Frankie", Stevie"]
teamOneArr - teamTwoArr
=> ["John"]
erik
  • 6,406
  • 3
  • 36
  • 36
  • 1
    This says teamOne and teamTwo are the same if teamTwoArr is a superset of teamOneArr. It needs to be ((teamOneArr - teamTwoArr) + (teamTwoArr - teamOneArr)) to find elements that are unique in teamOne *or* teamTwo. – Chuck Jan 09 '09 at 00:18
5

easy solution:

 def compare(a, b)
   diff = a.split(', ') - b.split(', ')
   if diff === [] // a and b are the same
     true
   else
     diff
   end
 end

of course this only works if your strings contain comma-separated values, but this can be adjusted to your situation.

gabriel
  • 1,787
  • 2
  • 19
  • 24
  • 2
    This says a and b are the same if b is a superset of a. It needs to be ((split_a - split_b) + (split_b - split_a)) to find elements that are unique in a *or* b. – Chuck Jan 09 '09 at 00:17
3

You need to sort first to ensure you are not subtracting a bigger string from a smaller one:

def compare(*params)
   params.sort! {|x,y| y <=> x}
   diff = params[0].split(', ') - params[1].split(', ')
   if diff === []
      true
   else
      diff
   end 
end

puts compare(a, b)
Aaron Rustad
  • 2,016
  • 17
  • 25
0

I understood the question in two ways. In case you wanted to do a string difference (word by word) which covers this case:

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

s1 = teamOne.split(' ')
s2 = teamTwo.split(' ')

diff = []
s1.zip(s2).each do |s1, s2|
  if s1 != s2
    diff << s1
  end
end

puts diff.join(' ')

Result is:

Tom, Stevie, John

Accepted answer gives:

#<Set: {"Zach", "John"}>
laimison
  • 1,409
  • 3
  • 17
  • 39