在Python中,你可以在一个列表推导式中有多个迭代器,比如

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

我知道Python的列表推导式的嵌套循环语义。

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

[x for x in a for a in b]

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

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

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

要实现这个结果,列表理解表达式是什么:

[1,2,3,4]

?? (请只列出理解性的答案,因为这是我想知道的)。


当前回答

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

>>> [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

其他回答

如果你想保持多维数组,就应该嵌套数组括号。参见下面的示例,其中每个元素都添加了一个。

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

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

>>> [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

在我第一次尝试的时候,我从来没有写过双表理解。读一读PEP202,你会发现原因是它的实施方式和你在英语中读到的完全相反。好消息是,这是一个逻辑上合理的实现,因此一旦您理解了结构,就很容易得到正确的实现。

设a, b, c, d是依次嵌套的对象。对我来说,扩展列表理解的直观方法是模仿英语:

# works
[f(b) for b in a]
# does not work
[f(c) for c in b for b in a]
[f(c) for c in g(b) for b in a]
[f(d) for d in c for c in b for b in a]

换句话说,你将从下往上阅读,即。

# wrong logic
(((d for d in c) for c in b) for b in a)

然而,这不是Python实现嵌套列表的方式。相反,实现将第一个块视为完全独立的块,然后从上到下(而不是从下到上)将for和in链接到单个块中,即。

# right logic
d: (for b in a, for c in b, for d in c)

请注意,嵌套最深的层(对于c中的d)距离列表(d)中的最后一个对象最远。这是因为Guido自己:

形式[…]x……y……]巢,最后一个索引变化最快,就像嵌套for循环一样。

使用Skam的文本示例,这变得更加清楚:

# word: for sentence in text, for word in sentence
[word for sentence in text for word in sentence]

# letter: for sentence in text, for word in sentence, for letter in word
[letter for sentence in text for word in sentence for letter in word]

# letter:
#     for sentence in text if len(sentence) > 2, 
#     for word in sentence[0], 
#     for letter in word if letter.isvowel()
[letter for sentence in text if len(sentence) > 2 for word in sentence[0] for letter in word if letter.isvowel()]

这个flat_nlevel函数递归调用嵌套的list1来转换到一个级别。试试这个

def flatten_nlevel(list1, flat_list):
    for sublist in list1:
        if isinstance(sublist, type(list)):        
            flatten_nlevel(sublist, flat_list)
        else:
            flat_list.append(sublist)

list1 = [1,[1,[2,3,[4,6]],4],5]

items = []
flatten_nlevel(list1,items)
print(items)

输出:

[1, 1, 2, 3, 4, 6, 4, 5]

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

[x for b in a for x in b]

为了得到想要的结果,一个当前值可以作为下一个循环的迭代器。