Python:处理两个列表的“Pythonic”方法是什么?

时间:2013-12-14 00:09:05

标签: python list list-comprehension

说我在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方法是什么?我认为列表理解可以做得很好,但我无法理解“过程两个单独的列表”这一部分。

3 个答案:

答案 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]