Wie eine Ruby-Array Kreuzung mit doppelten Elementen zurück? (Problem mit Bigramme in Dice Coefficient)

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

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?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top