Comment renvoyer une intersection de tableau Ruby avec des éléments en double? (problème de bigrammes dans le coefficient de dés)

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

Question

J'essaie d'écrire le coefficient de Dice, mais j'ai un problème avec l'intersection de tableaux.

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

Le problème est que, comme & amp; supprime les doublons, je reçois des choses comme celle-ci:

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

puts approx_string_match(string1, string2) => 76.0%

Il devrait renvoyer 100.

La méthode uniq la cloue, mais il y a une perte d'information qui peut amener des correspondances indésirables dans le jeu de données particulier sur lequel je travaille.

Comment puis-je obtenir une intersection avec tous les doublons inclus?

Était-ce utile?

La solution

Comme Yuval F a déclaré que vous devriez utiliser multiset . Cependant, il n'y a pas de multiset dans la bibliothèque standard Ruby, consultez ici et ici .

Si les performances ne sont pas critiques pour votre application, vous pouvez toujours le faire en utilisant Array avec un code un peu bit.

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"]

Autres conseils

De ce lien Je pense que vous ne devriez pas utiliser les ensembles de Ruby mais plutôt multisets, de sorte que chaque bigramme compte le nombre de fois où il apparaît. Peut-être pouvez-vous utiliser cette gem pour les multisets. Cela devrait donner un comportement correct pour les bigrammes récurrents.

Je me suis amusé avec cela pendant un certain temps, en me basant sur la réponse de @pierr, pour finir avec cela.

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"]

Cela pourrait être une sorte d'intersection multiset de a & amp; b mais ne vous fiez pas à ma parole car je ne l'ai pas suffisamment testée pour en être sûr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top