Wie eine Ruby-Array Kreuzung mit doppelten Elementen zurück? (Problem mit Bigramme in Dice Coefficient)
-
05-07-2019 - |
Frage
Ich versuche Skript Dice-Koeffizient, aber ich bin ein bisschen ein Problem mit der Array Kreuzung mit.
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
Das Problem ist, wie & Duplikate entfernt, ich Sachen wie diese:
string1="Almirante Almeida Almada"
string2="Almirante Almeida Almada"
puts approx_string_match(string1, string2) => 76.0%
Es sollte 100 zurück.
Die uniq Methode Nägel, aber es gibt Informationsverlust, der in der jeweiligen Datenmenge unerwünschte Begegnungen bringen kann ich arbeite.
Wie kann ich eine Kreuzung mit allen Duplikate erhalten enthalten?
Lösung
Wie Yuval F
gesagt, Sie sollten multiset
verwenden. Allerdings gibt es nomultiset
in Ruby-Standardbibliothek, bei Schauen Sie sich an hier und hier .
Wenn die Leistung nicht so kritisch für Ihre Anwendung ist, noch können Sie es tun usingArray
mit ein wenig Code.
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"]
Andere Tipps
diesem Link Ich glaube, Sie nicht Rubys Sets verwenden sollten sondern Multimengen, so dass jedes Bigramm wird die Anzahl der Male gezählt es erscheint. Vielleicht können Sie verwenden dieses Juwel für Multimengen . Dies sollte ein korrektes Verhalten geben Bigramme für wiederkehrend.
ich mit diesem gespielt, auf der Grundlage der Antwort von @pierr, für eine Weile und damit endete.
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"]
Dies könnte eine Art multiset intersect von a
& b
sein, aber nehmen Sie nicht mein Wort für es, weil ich es nicht getestet habe genug um sicher zu sein.