Python >> Tutoriel Python >  >> Python Tag >> RegEx

Python string occurrence count regex performance

OK, j'avais du mal à le faire fonctionner sans regexes, car nous savons tous que les regex sont lentes. Voici ce que j'ai trouvé :

def count_occurrences(word, text):
    spaces = [' ', '\n', '(', '«', '\u201d', '\u201c', ':', "''", "__"]
    endings = spaces + ['?', '.', '!', ',', ')', '"', '»']
    s = text.lower().split(word.lower())
    l = len(s)
    return sum((
            (i == 0 and (s[0] == '' or any(s[i].endswith(t) for t in spaces)) and (s[1] == '' or any(s[i+1].startswith(t) for t in endings))) 
            or (i == l - 2 and any(s[i].endswith(t) for t in spaces) and (s[i+1] == '' or any(s[i+1].startswith(t) for t in endings)))
            or (i != 0 and i != l - 2 and any(s[i].endswith(t) for t in spaces) and any(s[i+1].startswith(t) for t in endings))
        ) for i in range(l - 1))

L'ensemble du fichier s'exécute dans ideone :

Ran 1 test in 0.025s

OK

C'est ce que demande la question.

La logique est assez simple. Séparons le text par word , tous deux en minuscules. Regardons maintenant chaque couple de voisins. Si, par exemple, l'index 0 se termine par un délimiteur valide et que l'index 1 commence par un délimiteur valide, comptons-le comme une occurrence. Faisons-le jusqu'au dernier couple de la scission.

Étant donné que les performances sont importantes ici, nous devons être attentifs à l'ordre de spaces et endings . Nous recherchons essentiellement le premier de la liste pour remplir la condition. Il est donc important de localiser d'abord les variables les plus courantes. Par exemple, si je déclare :

spaces = ['(', '«', '\u201d', '\u201c', ':', "''", "__", '\n', ' ']

au lieu de ce que j'ai dans ma solution, j'obtiens une série de 0.036 secondes.

Si par exemple je déclare un tableau :

spaces = [' ', '\n', '(', '«', '\u201d', '\u201c', ':', "''", "__", '?', '.', '!', ',', ')', '"', '»']

qui a tous les délimiteurs et n'utilise que cela, j'obtiens 0,053 seconde. Soit 60 % de plus que ma solution.

Il est probablement possible qu'il existe une meilleure solution en déclarant les délimiteurs dans un autre ordre.