列表理解中的双重迭代[重复]

2025-01-15 08:46:00
admin
原创
76
摘要:问题描述:在 Python 中,你可以在列表推导中拥有多个迭代器,例如[(x,y) for x in a for y in b] 对于一些合适的序列 a 和 b。我知道 Python 列表推导的嵌套循环语义。我的问题是:理解中的一个迭代器可以引用另一个迭代器吗?换句话说:我是否可以有这样的事情:[x for ...

问题描述:

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

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


解决方案 1:

假设您有一段充满句子的文本,并且您想要一个单词数组。

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

例子:

>>> text = (("Hi", "Steve!"), ("What's", "up?"))
>>> [word for sentence in text for word in sentence]
['Hi', 'Steve!', "What's", 'up?']

这也适用于发电机

>>> text = (("Hi", "Steve!"), ("What's", "up?"))
>>> gen = (word for sentence in text for word in sentence)
>>> for word in gen: print(word)
Hi
Steve!
What's
up?

解决方案 2:

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

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

解决方案 3:

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

[x for b in a for x in b]

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

解决方案 4:

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

举个例子:[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)

解决方案 5:

这种记忆技术对我帮助很大:

[ <RETURNED_VALUE> <OUTER_LOOP1> <INNER_LOOP2> <INNER_LOOP3> ... <OPTIONAL_IF> ]

现在你可以认为R eturn +循环是唯一正确顺序

了解上述内容后,即使对于 3 个循环,列表中的顺序也看起来很简单:


c=[111, 222, 333]
b=[11, 22, 33]
a=[1, 2, 3]

print(
  [
    (i, j, k)                            # <RETURNED_VALUE> 
    for i in a for j in b for k in c     # in order: loop1, loop2, loop3
    if i < 2 and j < 20 and k < 200      # <OPTIONAL_IF>
  ]
)
[(1, 11, 111)]

因为上面只是一个:

for i in a:                         # outer loop1 GOES SECOND
  for j in b:                       # inner loop2 GOES THIRD
    for k in c:                     # inner loop3 GOES FOURTH
      if i < 2 and j < 20 and k < 200:
        print((i, j, k))            # returned value GOES FIRST

对于迭代一个嵌套列表/结构,技术是相同的:对于a问题:

a = [[1,2],[3,4]]
[i2    for i1 in a      for i2 in i1]
which return [1, 2, 3, 4]

嵌套级别

a = [[[1, 2], [3, 4]], [[5, 6], [7, 8, 9]], [[10]]]
[i3    for i1 in a      for i2 in i1     for i3 in i2]
which return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

等等

解决方案 6:

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]

解决方案 7:

我第一次尝试写出双重列表推导式时,总是写不出来。读了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 实现嵌套列表的方式。相反,实现将第一个块视为完全独立的,然后从上到下(而不是从下到上)将fors 和s 链接在一个块中,即in

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

请注意,最深的嵌套级别(for d in c)距离列表中的最后一个对象最远(d)。原因来自 Guido 本人:

该形式[... for x... for 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()]

解决方案 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]

解决方案 9:

我觉得这更容易理解

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

result: [1, 2, 3, 4]

解决方案 10:

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

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定义我们想要返回的内容。

解决方案 11:

此 flatten_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]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用