Python 的 itertools.compress 不像布尔掩码那样工作。为什么?

我有一个字符串列表,我想使用itertools.compress.


我有大量的字符串需要对照句子列表进行检查。因此,我想使用 itertools 来节省资源。无法按预期工作的部分是通过压缩进行的布尔屏蔽。


from itertools import product, starmap, compress


def is_in(string, other_string):

    return string in other_string


to_find = ['hello', 'bye']

some_sentences = ['hello to you', ' hello and bye', 'bye bye']


cartesian = product(to_find, some_sentences)

matched_mask = starmap(is_in, cartesian)

matched = compress(cartesian, matched_mask)

print(list(matched))

actual_result = [('hello', 'hello to you'), ('bye', ' hello and bye')]


expected = [('hello', 'hello to you'), 

           ('hello', 'hello and bye'),

           ('bye', ' hello and bye'), 

           ('bye', 'bye bye')]


潇湘沐
浏览 171回答 1
1回答

慕的地6264312

itertools.product返回一个迭代器,迭代器一般都是“single-pass”的(可能有例外)。一旦一个元素被迭代,它就不会被再次迭代。但是,您可以itertools.product在两个地方使用结果,一次作为 for 的参数,一次作为 for 的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')]在这种情况下,我认为生成器函数中的循环比使用 multiple 更具可读性itertools:from itertools import productdef 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')]
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python