Après avoir répondu à une question ici sur le SO de trouver une ville dans une question fournie par l'utilisateur , je commencé à penser à la meilleure façon de recherche d'une chaîne dans un texte lorsque vous avez un ensemble de données limité comme celui-ci.Rechercher une chaîne dans un texte
in
et find
correspond à une sous-chaîne, ce qui n'est pas souhaitable. Exiger les expressions utilisant des "limites de mots" fonctionnent mais sont assez lentes. L'approche "ponctuation" semble être un candidat, mais il y a beaucoup de ponctuation characters qui peuvent apparaître à la fois en question ainsi que certains dans le nom d'une ville (c'est-à-dire une période dans "St. Louis").
Les expressions rationnelles sont probablement la meilleure solution à usage général, mais je suis curieux de savoir si cela peut être résolu en utilisant une autre technique.
La tâche consiste à:
Trouver une ville aux États-Unis dans un texte fourni par l'utilisateur dans la langue anglaise quel que soit le cas.
Mon code fortement inspiré par http://www.python.org/doc/essays/list2str/
#!/usr/bin/env python
import time
import re
def timing(f, n):
print f.__name__,
r = range(n)
t1 = time.clock()
for i in r:
f(); f(); f(); f(); f(); f(); f(); f(); f(); f()
t2 = time.clock()
print round(t2-t1, 6)
def f0():
'''broken since it finds sub-strings, e.g.
city "Erie" is found in "series"'''
Q = question.upper()
for c in cities:
c = c.upper()
if c in Q:
pass
def f1():
'''slow, but working'''
for c in cities:
re.search('\\b%s\\b' % c, question, re.IGNORECASE)
def f2():
'''broken, same problem as f0()'''
Q = question.upper()
for c in cities:
c = c.upper()
if Q.find(c) > 0:
pass
def f3():
'''remove all punctuation, and then search for " str " '''
Q = question.upper()
punct = ['.', ',', '(', ')', '"', '\n', ' ', ' ', ' ']
for p in punct:
Q = Q.replace(p, ' ')
for c in cities:
c = ' ' + c.upper() + ' '
for p in punct:
c = c.replace(p, ' ')
if c in Q:
pass
with open('cities') as fd:
cities = [line.strip() for line in fd]
with open('question') as fd:
question = fd.readlines()[0]
testfuncs = f0, f1, f2, f3
for f in testfuncs:
print f
timing(f, 20)
Sur mon vieux portable louches, je reçois les résultats suivants
<function f0 at 0xb7730bc4>
f0 0.14
<function f1 at 0xb7730f7c>
f1 10.4
<function f2 at 0xb7730f44>
f2 0.15
<function f3 at 0xb7738684>
f3 0.61
Si quelqu'un aimerait avoir un aller sur mon testdata, il peut être trouvé here
Un autre test utile pourrait être en utilisant un modèle de regex pré-compilé. – trutheality
Vous pouvez compiler une grande regex pour correspondre à n'importe quel nom de ville. Il ressemble '' "(% s)"% "|" .join (re.escape (c) pour c dans les villes) '. –