【问题标题】:How do you repeat a list within a list comprehension?你如何在列表理解中重复一个列表?
【发布时间】:2020-12-14 00:56:17
【问题描述】:

我正在提高我的列表理解能力,寻找练习来加深我的理解。但我已经达到了一个我似乎无法绕过的地方。假设我想要一个包含范围(1,3)中3个随机数字的所有可能列表的列表,其中每个列表的总和不等于3。

[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 1], [0, 2, 0] ...]

显然,我需要使用嵌套列表推导来做到这一点。但我不确定该怎么做。据我所知,我无法将列表分配给列表理解中的变量。但我需要该变量来引用输出:

list7 = [[randint(0,2) for x in range(3)] for y if sum(y) != 3]

这给了我一个语法错误。我已经尝试先将内部列表分配给一个变量,但这似乎也不起作用:

y = [randint(0,2) for x in range(3)]
list7 = [y for y if sum(y) != 3]

不过,让我感到困惑的是,“y”在这里根本没有给出任何错误。即使 randint 没有分配给“x”,它的行为也符合我的预期。显然这里有一些我不明白的地方。所以,这是我的问题:如果我不能将嵌套列表分配给理解中的变量,我该如何在列表理解中重复嵌套列表?提前致谢。

【问题讨论】:

  • 尝试由内而外地工作,以确保您了解您的数据结构及其内容。 List comprehensions 在 python 文档中得到了很好的描述,包括一个非常接近你的例子。此外,解决您自己的语法问题将教给您的不仅仅是在这里得到答案。
  • 如果我能得到的唯一帮助是“去阅读文档并尝试解决你自己的问题”,彼得,我看不到堆栈溢出的意义。我一直在这样做,我遇到了麻烦。这就是我来这里的原因。
  • 外部列表推导不是list7 中的列表推导,因为没有任何东西被迭代。 IE。 in foo 子句。
  • @PleasantNightmares 很抱歉你有这种感觉。正如@dpwrussel 指出的那样,您的第二个列表理解中没有in。有些事情只需要反复琢磨、重新检查等。你会明白的。

标签: list list-comprehension


【解决方案1】:

正如我在评论中指出的那样,您的解决方案的一个问题是外部列表理解没有可迭代的。那么它如何知道要产生多少结果,或者什么时候停止产生结果呢?

您的if 子句也有问题。在您的if 中,您执行sum(y),我认为它的意思是“对[randint(0,2) for x in range(3)] 的结果求和”。这是倒退的,因为if 首先执行。此外,y 是迭代器中当前项目的循环变量,而不是该项目的列表推导结果。

您的解决方案的另一个问题是您使用的是randint。因此,您可能会多次产生某些组合,而其他组合则根本不会。这有点离题了。

我认为您可能希望将这样的内容转换为列表理解。

results = []
for i in range(3):
    for j in range(3):
        for k in range(3):
            if i + j + k != 3:
                results.append([i, j, k])

这是完全可行的,但答案不是嵌套列表推导,因为那是当您需要生成列表列表时,在这种情况下,只有您的外部列表需要推导,您的内部列表只有 3 位数一个容器。它也可以很容易地成为一个元组。

最好从您想要最终得到的结果(列表列表)的角度来考虑这一点。这意味着您需要生成一个包含其他列表的列表。

所以你想生成这 3 位数字,检查它们是否加起来为 3,如果不是,它们是作为列表添加到结果中的项目之一。您可以利用 Python 中的列表推导式支持多个迭代器这一事实来实现与嵌套 for 循环相同的功能。

results = [
    [i, j, k] 
    for i in range(3) for j in range(3) for k in range(3)
    if i + j + k != 3
]

有关更多有用示例,请参阅官方文档:http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions


编辑:

我突然想到你想做的是这样的:

results = [
    item for item in [
        [i, j, k] 
        for i in range(3) for j in range(3) for k in range(3)
    ]
    if sum(item) != 3
]

这看起来更像您的代码。这在结果方面是等效的,但性能可能会低很多(在进程和内存方面),因为在此示例中,您将所有 [i, j, k] 可能性构建到一个列表中,然后将它们过滤到那些加起来不要等于 3。最好根本不构建这些列表。对于这个微不足道的示例,它几乎没有什么区别,但如果 [x, y, z] 的构建成本很高,或者每个项目都使用了不小的内存量,那么它可能很重要。

【讨论】:

  • 或只是[t for t in [(x, y, z) for x in range(3) for y in range(3) for z in range(3)] if sum(t) != 3] 过度使用列表理解。
  • 这与我的替代解决方案完全相同,只是写在一行中,并为容器使用了一个元组!
猜你喜欢
  • 1970-01-01
  • 2019-08-13
  • 2020-07-09
  • 2016-09-08
  • 1970-01-01
  • 2018-01-01
  • 2021-10-30
  • 1970-01-01
  • 2013-01-26
相关资源
最近更新 更多