说我在Python中有这个代码。我是Perl程序员,你可能会说。
# Both list1 and list2 are a list of strings
for x in list1:
for y in list2:
if y in x:
return True
return False
处理此问题的更多Pythonic方法是什么?我认为列表理解可以做得很好,但我无法理解“过程两个单独的列表”这一部分。
答案 0 :(得分:8)
要将两个嵌套循环转换为嵌套理解,您只需执行以下操作:
[<expression> for x in list1 for y in list2]
如果您从未考虑过列表推导的工作方式,那么教程explains it:
列表推导由括号组成,括号中包含一个表达式,后跟一个for子句,然后是零个或多个for或if子句。结果将是一个新的列表,该列表是通过在其后面的for和if子句的上下文中计算表达式而得到的。
换句话说,理解中从左到右的条款与从顶部/外部到底部/内部的陈述相匹配,这就是它的全部内容。
This blog post试图以另一种方式提出相同的想法,以防你还没有得到它。
但是在这里,你没有表达,你有一个声明。
但是你有一个表达式,语句的y in x
部分,如果任何值都是真的,那么你想要做的就是返回True,这正是any
的作用。所以:
return any([y in x for x in list1 for y in list2])
实际上,你不想在这里构建列表,只是遍历值,所以删除方括号使其成为生成器表达式:
return any(y in x for x in list1 for y in list2)
对于只迭代多个迭代的笛卡尔积的简单情况,您可能希望使用itertools.product
代替。在这种情况下,我认为它不会使事情变得更简单或更具可读性,但如果你有四个列表而不是两个 - 或者预先不可预测的数量 - 这可能是一个不同的故事:
return any(y in x for x, y in product(list1, list2))
答案 1 :(得分:4)
不,列表理解不能很好。你想要一个布尔结果,列表推导用于创建列表(并且它们并不真正提前退出)。你可以使用生成器理解:
return any(y in x for x, y in itertools.product(list1, list2))
或者如果您真的喜欢使用标准库(或者您认为像功能程序员一样):
from itertools import starmap, product
from operator import contains
return any(starmap(contains, product(list1, list2))
答案 2 :(得分:0)
Steve和abamarts的答案正在解释你明确提出的问题,我会尝试解决你对列表理解所暗示的内容。
“嵌套”列表理解仅仅是你原来的嵌套for循环,但随着扭曲,最内部的块移动到顶部!
for x in list1:
for y in list2:
if y in x:
return True
else:
return False
变为:
[True if y in x else False for x in list1 for y in list2]
因此for循环或多或少依旧:
[for x in list1 for y in list2]
然后添加if子句:
[if y in x else False for x in list1 for y in list2]
最后将if语句的结果前置为True:
[True if y in x else False for x in list1 for y in list2]
嵌套示例:
tpl_list = []
for element in vector:
for x, y in element:
if (x**2+y**2) < 1:
tpl_list.append((1/x, 1/y))
else:
tpl_list.append((x,y))
作为列表理解(按步骤构建)
[for e in vector for x,y in e]
[if (x**2+y**2) < 1 else for e in vector for x,y in e]
[(1/x, 1/y) if (x**2+y**2) < 1 else (x,y) for e in vector for x,y in e]