2

我正在尝试编写 Dice's Coefficient 脚本,但数组交集有点问题。

def bigram(string)
  string.downcase!
  bgarray=[]
  bgstring="%"+string+"#"
  bgslength = bgstring.length
  0.upto(bgslength-2) do |i|
    bgarray << bgstring[i,2]
   end
   return bgarray
 end

def approx_string_match(teststring, refstring)
  test_bigram = bigram(teststring) #.uniq
  ref_bigram = bigram(refstring)   #.uniq

  bigram_overlay = test_bigram & ref_bigram

  result = (2*bigram_overlay.length.to_f)/(test_bigram.length.to_f+ref_bigram.length.to_f)*100

  return result
end

问题是,当 & 删除重复项时,我得到这样的东西:

string1="Almirante Almeida Almada"
string2="Almirante Almeida Almada"

puts approx_string_match(string1, string2) => 76.0%

它应该返回 100。

uniq 方法可以解决问题,但存在信息丢失,这可能会在我正在工作的特定数据集中带来不需要的匹配。

如何获得包含所有重复项的交集?

4

3 回答 3

4

如前所述Yuval F,您应该使用multiset. multiset但是, Ruby 标准库中没有,请看这里这里

如果性能对您的应用程序不是那么重要,您仍然可以使用Array一点代码来完成它。

def intersect  a , b  
    a.inject([]) do |intersect, s|
      index = b.index(s)
      unless index.nil?
         intersect << s
         b.delete_at(index)
      end
      intersect        
    end
end

a=  ["al","al","lc" ,"lc","ld"]
b = ["al","al" ,"lc" ,"ef"]
puts intersect(a ,b).inspect   #["al", "al", "lc"]
于 2009-10-21T12:38:47.193 回答
1

这个链接我相信你不应该使用 Ruby 的集合,而应该使用多重集合,这样每个二元组都会被计算它出现的次数。也许您可以将这个 gem用于多组。这应该为重复出现的二元组提供正确的行为。

于 2009-10-21T11:44:44.287 回答
0

根据@pierr的回答,我玩弄了一段时间,最终得到了这个。

a = ["al","al","lc","lc","lc","lc","ld"]
b = ["al","al","al","al","al","lc","ef"]
result=[]
h1,h2=Hash.new(0),Hash.new(0)
a.each{|x| h1[x]+=1}
b.each{|x| h2[x]+=1}
h1.each_pair{|key,val| result<<[key]*[val,h2[key]].min if h2[key]!=0}
result.flatten

=> ["al", "al", "lc"]

a这可能是&的一种多集相交,b但不要相信我的话,因为我没有对其进行足够的测试来确定。

于 2010-02-17T11:29:17.003 回答