列表理解中的双重迭代

问题描述 投票:177回答:8

在Python中,您可以在列表推导中使用多个迭代器,例如

[(x,y) for x in a for y in b]

对于一些合适的序列a和b。我知道Python列表推导的嵌套循环语义。

我的问题是:理解中的一个迭代器可以指向另一个吗?换句话说:我可以这样:

[x for x in a for a in b]

外循环的当前值是内部的迭代器?

例如,如果我有一个嵌套列表:

a=[[1,2],[3,4]]

列表理解表达式将实现此结果:

[1,2,3,4]

?? (请仅列出理解答案,因为这是我想要找到的)。

python list-comprehension
8个回答
141
投票

用你自己的建议回答你的问题:

>>> [x for b in a for x in b] # Works fine

当你要求列表理解答案时,我还要指出优秀的itertools.chain():

>>> from itertools import chain
>>> list(chain.from_iterable(a))
>>> list(chain(*a)) # If you're using python < 2.6

118
投票

我希望这有助于其他人,因为a,b,x,y对我没有多大意义!假设你有一个充满句子的文本,你想要一组单词。

# Without list comprehension
list_of_words = []
for sentence in text:
    for word in sentence:
       list_of_words.append(word)
return list_of_words

我喜欢将列表理解视为水平拉伸代码。

尝试将其分解为:

# List Comprehension 
[word for sentence in text for word in sentence]

106
投票

哎呀,我想我找到了答案:我没有足够关心哪个循环是内部的,哪个是外部的。列表理解应该是:

[x for b in a for x in b]

获得所需的结果,是的,一个当前值可以是下一个循环的迭代器。


40
投票

迭代器的顺序可能看起来违反直觉。

举个例子:[str(x) for i in range(3) for x in foo(i)]

让我们分解它:

def foo(i):
    return i, i + 0.5

[str(x)
    for i in range(3)
        for x in foo(i)
]

# is same as
for i in range(3):
    for x in foo(i):
        yield str(x)

18
投票

ThomasH已经添加了一个很好的答案,但我想说明会发生什么:

>>> a = [[1, 2], [3, 4]]
>>> [x for x in b for b in a]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

>>> [x for b in a for x in b]
[1, 2, 3, 4]
>>> [x for x in b for b in a]
[3, 3, 4, 4]

我猜Python从左到右解析列表理解。这意味着,将首先执行发生的第一个for循环。

第二个“问题”是b从列表理解中“泄露”出来。第一次成功列表理解后b == [3, 4]


8
投票

如果要保留多维数组,则应该嵌套数组括号。请参阅下面的示例,其中一个添加到每个元素。

>>> a = [[1, 2], [3, 4]]

>>> [[col +1 for col in row] for row in a]
[[2, 3], [4, 5]]

>>> [col +1 for row in a for col in row]
[2, 3, 4, 5]

3
投票

我觉得这更容易理解

[row[i] for row in a for i in range(len(a))]

result: [1, 2, 3, 4]

3
投票

此外,您可以对当前访问的输入列表的成员以及此成员中的元素使用相同的变量。然而,这甚至可能使它更多(列表)难以理解。

input = [[1, 2], [3, 4]]
[x for x in input for x in x]

首先评估for x in input,导致输入的一个成员列表,然后,Python遍历第二部分for x in x,在此期间x值被它正在访问的当前元素覆盖,然后第一个x定义我们想要返回的内容。

© www.soinside.com 2019 - 2024. All rights reserved.