Einige Versuche mit etwas Profilierung. Ich dachte, die Verwendung von Generatoren könnte hier die Geschwindigkeit verbessern. Aber die Verbesserung war im Vergleich zu einer leichten Modifikation des Originals nicht bemerkbar. Aber wenn Sie nicht die vollständige Liste gleichzeitig benötigen, sollten die Generatorfunktionen schneller sein.
import timeit
from itertools import tee, izip, islice
def isplit(source, sep):
sepsize = len(sep)
start = 0
while True:
idx = source.find(sep, start)
if idx == -1:
yield source[start:]
return
yield source[start:idx]
start = idx + sepsize
def pairwise(iterable, n=2):
return izip(*(islice(it, pos, None) for pos, it in enumerate(tee(iterable, n))))
def zipngram(text, n=2):
return zip(*[text.split()[i:] for i in range(n)])
def zipngram2(text, n=2):
words = text.split()
return pairwise(words, n)
def zipngram3(text, n=2):
words = text.split()
return zip(*[words[i:] for i in range(n)])
def zipngram4(text, n=2):
words = isplit(text, ' ')
return pairwise(words, n)
s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
s = s * 10 ** 3
res = []
for n in range(15):
a = timeit.timeit('zipngram(s, n)', 'from __main__ import zipngram, s, n', number=100)
b = timeit.timeit('list(zipngram2(s, n))', 'from __main__ import zipngram2, s, n', number=100)
c = timeit.timeit('zipngram3(s, n)', 'from __main__ import zipngram3, s, n', number=100)
d = timeit.timeit('list(zipngram4(s, n))', 'from __main__ import zipngram4, s, n', number=100)
res.append((a, b, c, d))
a, b, c, d = zip(*res)
import matplotlib.pyplot as plt
plt.plot(a, label="zipngram")
plt.plot(b, label="zipngram2")
plt.plot(c, label="zipngram3")
plt.plot(d, label="zipngram4")
plt.legend(loc=0)
plt.show()
Für diese Testdaten scheint ziprngram2 und zigngram3 mit Abstand am schnellsten zu sein.

Sind Sie in Ordnung mit separaten Funktionen für verschiedene Werte von 'n'? Das Festcodieren in 'zipngram' und das Entfernen des Listenausdrucks bietet eine 1,5-2x-Beschleunigung in einigen groben Experimenten. – dmcc
sicher, jede Methode, solange es schneller ist und die gleiche Ausgabe =) erreichen. kümmern sich um den Code und einige Profiler teilen? – alvas
Zählen Implementierungen in Cython oder C über 'cffi'? Diese wären am schnellsten, obwohl nicht trivial, wenn das Alphabet Unicode ist und nicht etwa ACSII. Wenn es das letztere wäre, würde die SSE-Versammlung wahrscheinlich in den Arsch treten. Darüber hinaus möchten Sie möglicherweise die Arbeit über Kerne verteilen, wenn Text lang genug ist. –