itertools.product
возвращает итератор, и итераторы обычно являются однопроходными (возможны исключения). Как только элемент повторяется, он не повторяется снова.
Однако вы используете результат itertools.product
в двух местах: один раз в качестве аргумента для starmap
и один раз в качестве аргумента для compress
. Таким образом, если starmap
«вытолкнет» элемент из product
, то в следующий раз compress
«вытолкнет» элемент из того же продукта, он получит следующий элемент (не тот же элемент).
В большинстве случаев я бы рекомендовал не назначать такие итераторы в качестве переменных именно из-за их "однопроходного" характера.
Итак, очевидным решением было бы сгенерировать продукт дважды:
matched_mask = starmap(is_in, product(to_find, some_sentences))
matched = compress(product(to_find, some_sentences), matched_mask)
print(list(matched))
# [('hello', 'hello to you'), ('hello', ' hello and bye'), ('bye', ' hello and bye'), ('bye', 'bye bye')]
В этом случае я думаю, что цикл в функции генератора будет более читабельным, чем использование нескольких itertools
:
from itertools import product
def func(to_find, some_sentences):
for sub, sentence in product(to_find, some_sentences):
if sub in sentence:
yield sub, sentence
А затем используйте это так:
>>> to_find = ['hello','bye']
>>> some_sentences = ['hello to you', ' hello and bye', 'bye bye']
>>> list(func(to_find, some_sentences))
[('hello', 'hello to you'),
('hello', ' hello and bye'),
('bye', ' hello and bye'),
('bye', 'bye bye')]
Или, если вам нравятся однострочники:
>>> [(sub, sentence) for sub, sentence in product(to_find, some_sentences) if sub in sentence]
[('hello', 'hello to you'),
('hello', ' hello and bye'),
('bye', ' hello and bye'),
('bye', 'bye bye')]