Конечно, вы можете легко написать это как понимание списка:
[(a, b) for a in A for b in B if a in b]
Это может немного ускорить цикл, но не стоит ожидать слишком многого.Я сомневаюсь, что использование регулярных выражений поможет в любом случае с этим.
Редактировать : Вот некоторые моменты:
import itertools
import timeit
import re
import collections
with open("/usr/share/dict/british-english") as f:
A = [s.strip() for s in itertools.islice(f, 28000, 30000)]
B = [s.strip() for s in itertools.islice(f, 23000, 25000)]
def f():
result = []
for a in A:
for b in B:
if a in b:
result.append((a, b))
return result
def g():
return [(a, b) for a in A for b in B if a in b]
def h():
res = [re.compile(re.escape(a)) for a in A]
return [(a, b) for a in res for b in B if a.search(b)]
def ninjagecko():
d = collections.defaultdict(set)
for k, b in enumerate(B):
for i, j in itertools.combinations(range(len(b) + 1), 2):
d[b[i:j]].add(k)
return [(a, B[k]) for a in A for k in d[a]]
print "Nested loop", timeit.repeat(f, number=1)
print "List comprehension", timeit.repeat(g, number=1)
print "Regular expressions", timeit.repeat(h, number=1)
print "ninjagecko", timeit.repeat(ninjagecko, number=1)
Результаты:
Nested loop [0.3641810417175293, 0.36279606819152832, 0.36295199394226074]
List comprehension [0.362030029296875, 0.36148500442504883, 0.36158299446105957]
Regular expressions [1.6498990058898926, 1.6494300365447998, 1.6480278968811035]
ninjagecko [0.06402897834777832, 0.063711881637573242, 0.06389307975769043]
Редактировать 2: Добавлен вариант алогрита, предложенного ninjagecko к таймингу.Вы можете видеть, что это намного лучше, чем все методы грубой силы.
Редактировать 3: Использовать наборы вместо списков для устранения дубликатов.(Я не обновлял сроки - они остались практически без изменений.)