开发者

How to calculate number of chars common to two strings?

How would you calculate the intersection of characters between two strings?

For example (assuming we would have a method called String.intersection):

"abc".intersection("ab") = 2
"hello".intersection("hallo") = 4

Ok, boys and girls, thanks for your massive feedback. Some more examples:

"aaa".intersection("a") = 1
"foo".intersection("bar") = 0
"abc".intersection("bc") = 2
"abc".intersection("ac") = 2
"abba".intersection("aa") = 2

Some m开发者_StackOverflow社区ore notes: Wikipedia defines intersection as follows:

Intersection of the sets A and B, denoted A ∩ B, is the set of all objects that are members of both A and B. The intersection of {1, 2, 3} and {2, 3, 4} is the set {2, 3}


Use String#count:

irb(main):001:0> "hello".count("hallo")
=> 4
irb(main):002:0> "abc".count("ab")
=> 2


This passes all your described test cases:

class String
  def intersection(other)
    str = self.dup
    other.split(//).inject(0) do |sum, char|
      sum += 1 if str.sub!(char,'')
      sum
    end
  end
end


I'd use something like:

'abc'.split('') & 'ab'.split('') #=> ["a", "b"]
'hello'.split('') & 'yellow'.split('') #=> ["e", "l", "o"]

If you want a method to do it:

class String
  def intersection(other)
    self.split('') & other.split('')
  end
end
'hello'.intersection('yellow') #=> ["e", "l", "o"]
'now is the time for all good men to come to the aid of their country'.intersection('jackdaws love my giant sphinx of quartz')
=> ["n", "o", "w", " ", "i", "s", "t", "h", "e", "m", "f", "r", "a", "l", "g", "d", "c", "u", "y"]

To get the number of characters in common just tack on .size:

'hello'.intersection('yellow').size #=> 3

If you want the count of all matching common characters:

'hello'.count('hello'.intersection('yellow').join) #=> 4

Traditionally we'd do it by building a hash using each character in the first string, along with a counter, then walk through the second string incrementing the counter for each common character:

asdf = Hash[*'hello'.split('').map{ |s| [s, 0]}.flatten] #=> {"l"=>0, "o"=>0, "e"=>0, "h"=>0}
'yellow'.split('').each{ |s| asdf[s] += 1 if (asdf.key?(s)) }
asdf #=> {"l"=>2, "o"=>1, "e"=>1, "h"=>0}

The number of common characters:

asdf.select{ |n,v| v > 0 }.size #=> 3

The count of the common characters:

asdf.values.inject(0){ |m,i| m += i } #=> 4


Basically summing up the minimum number of occurences of each common character:

class String
  def intersection(compared_to)
    common_chars = (self.split('') & compared_to.split(''))
    common_chars.inject(0) { |result, char|
      result + [self.count(char), compared_to.count(char)].min
    }
  end
end

Results:

"abc".intersection("ab")      #=> 2
"hello".intersection("hallo") #=> 4
"aaa".intersection("a")       #=> 1
"foo".intersection("bar")     #=> 0
"abc".intersection("bc")      #=> 2
"abc".intersection("ac")      #=> 2
"abba".intersection("aa")     #=> 2


Using scan method to convert string into array and using & intersection operator you can do like this...

('abd'.scan(/./) & 'abc'.scan(/./)).length


the easiest for me is the utilize the array intersection operator & like below

class String
  def intersection(other)
    str = self.dup
    str.chars & other.chars
  end
end

usage like

"hello".intersection("hiho") // => ['h', '0']
"hello".intersection("hiho").size // => 2
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜