2009-12-06 4 views
0

J'ai deux tableaux de chaînes, par exemple des phrases et des mots. Si un mot est trouvé dans une phrase, par ex. sentence =~ /#{word}/ Je veux rejeter la phrase du tableau de phrases. C'est facile à faire avec une double boucle, mais je me demande s'il y a une façon plus efficace de le faire, peut-être avec des opérateurs logiques?Comment rejeter efficacement les chaînes dans un tableau si elles (regex) correspondent à des chaînes dans un second tableau dans Ruby?

+0

En relisant cela, on ne sait pas ce que vous entendez par « Je veux rejeter du tableau » - vous rejetez les éléments du tableau de mots ou le tableau de phrases? –

+0

Droit, déroutant. Clarifié. – Matt

Répondre

0

Vous pourriez joindre tous les mots ensemble dans une expression régulière, avec les mots séparés par le "|" personnage.

sentence =~ /word1|word2|..../ 

Vous pouvez convertir le tableau de mots en une expression rationnelle appropriée avec array.join ("|").

Si les mots sont susceptibles de contenir des métacaractères regex, placez chaque mot entre parenthèses sans capture.

sentence =~ /(?:word1)|(?:word2)|..../ 

En utilisant une seule regex devrait être beaucoup plus efficace que boucle à travers le réseau de mots, puisque le regex sera compilé dans un seul statetable.

+0

Nice! J'ai oublié cette approche. Merci. Va le comparer à la réponse de perimosocordiae. – Matt

+0

Dave - que fait le format # ~ dans ce cas? Vouliez-vous dire = ~? – Matt

+0

Oups - le # ~ était une faute de frappe - je voulais dire = ~ –

1

Array subtraction est votre ami ici:

words.each do |word| 
    sentences -= sentences.grep(/#{word}/) 
end 

Il est toujours la même complexité temporelle de base (probablement globalement moins efficace), mais vous pouvez obtenir autour de l'écriture la double boucle. Sachez qu'avec cette solution, les mots ne doivent pas nécessairement correspondre à des mots entiers séparés par des espaces dans la phrase. Ainsi, le mot cat écraserait la phrase: String concatenation is gross.

+0

Merci p. Faire quelque chose de similaire en ce moment mais votre version un peu plus jolie. Conscient des problèmes de regex, je voulais juste un exemple simple pour illustrer le problème. – Matt

0
words = [...] 
sentences = [....] 

result = sentences.select{|sentence| !words.any?{|word| sentence =~ /#{word}/}} 
1

Joining cordes dans une expression rationnelle est une idée assez mauvaise, car retours en arrière ralentit les choses horriblement et parce que vous exécutez dans des limites sur la taille de regex assez rapidement. (Bien que cela puisse bien fonctionner dans la pratique si wordarray est petit)

Envisagez d'utiliser l'une des solutions Ruby Quiz DictionaryMatcher.

Vous pouvez alors fonctionner comme suit:

dm=DictionaryMatcher.new 
wordarray.each{|w| dm << w} 
sentencearray.reject{|s| s =~ dm} 
+0

Merci beaucoup pour les pointeurs, les arbres de préfixe sont cool, et en fait j'ai un commentaire dans le code existant pour les vérifier pour ce problème. – Matt

+0

Ce n'est pas le préfixe-arbres qui est cool. C'est le jumelage de Knuth-Morris-Pratt qui est cool, bien qu'il y ait un autre algorithme moins efficace sur le plan théorique dans les solutions qui ont néanmoins été mieux référencées. –

Questions connexes