重複した要素を持つRuby配列交差を返す方法は? (サイコロ係数のバイグラムの問題)

StackOverflow https://stackoverflow.com/questions/1600168

質問

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

問題は、&amp;重複を削除すると、次のようなものが得られます。

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

puts approx_string_match(string1, string2) => 76.0%

100を返す必要があります。

uniqメソッドはそれを打ち消しますが、情報の損失があり、作業中の特定のデータセットに不要な一致をもたらす可能性があります。

すべての重複が含まれる交差点を取得するにはどうすればよいですか

役に立ちましたか?

解決

Yuval F が言ったように、 multiset を使用する必要があります。ただし、Ruby標準ライブラリには multiset はありません。こちらおよびこちら

アプリケーションのパフォーマンスがそれほど重要ではない場合でも、少しのコードで 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"]

他のヒント

このリンクからRubyのセットを使用すべきではないと考えていますむしろマルチセットなので、すべてのバイグラムが出現回数をカウントします。多分、このgem をマルチセットに使用できます。これにより、繰り返しバイグラムの正しい動作が得られるはずです。

しばらくの間、@ 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

=&gt; [&quot; al&quot;、&quot; al&quot;、&quot; lc&quot;】

これは、 a &amp;のマルチセット交差のようなものです。 b ですが、十分なテストを行っていないので、言葉を口にしないでください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top