2009-10-21 25 views
2

我试图脚本骰子的系数,但我有一点与阵列相交的问题。如何返回具有重复元素的Ruby数组交集? (问题与骰子系数的双字母组)

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

正如Yuval F说,你应该使用multiset。然而,在Ruby的标准库中没有multiset,在看采取在herehere

如果性能是不是为您的应用程序的关键,你仍然可以使用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"] 
+1

我很欣赏皮尔。你发布的代码做的是trick =)ty – Rui 2009-10-21 13:10:12

1

this link我相信你不应该使用Ruby的集合,而是使用多集合,这样每个二元组都会被计算出来的次数。也许你可以使用this gem进行多重播放。这应该为循环bigrams提供正确的行为。

+0

tyvm,ATM测试它。 – Rui 2009-10-21 11:59:54

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多集相交的,但因为我没有测试它足以确保不要把我的话。