【问题标题】:Python list comprehensions: Is it possible to specify the inclusion of two elements at a time?Python 列表推导:是否可以一次指定包含两个元素?
【发布时间】:2023-03-17 03:56:01
【问题描述】:

到目前为止,在 Python 中,我只见过指定一次包含一个元素的列表推导。例如,它们都是下面的形式

[f(x) for x in <iterable>]

有没有办法一次指定多个元素?例如,

[f(x), g(x) for x in <iterable>]

我问是因为我想创建一个列表推导来计算某个数字 x 的所有除数,但我想尽可能高效地做到这一点。现在我正在使用以下,

[y for y in range(1,x+1) if x%y == 0]

但我想做这样的事情,

[y, x/y for y in range(1, sqrt(x)+1) if x%y == 0]

因为这样会更有效率。顺便说一句,我没有这样做的实际理由。有人告诉我这只是一个具有挑战性的问题,目标是尽可能使用最小、最有效的列表理解来完成。

提前致谢。

编辑:好的,看来我必须使用元组。我试图避免这种情况,因为我必须创建另一个函数来展平列表,这会使我的解决方案更长。

编辑 2:以防万一有人偶然发现这个问题,我在原始问题中想要做的答案是这样的:

[y for x in <iterable> for y in f(x), g(x)]

它在列表推导中使用嵌套的 for 循环来完成工作。

【问题讨论】:

  • 从你的问题和我面前的答案看来,你应该阅读嵌套列表理解。前段时间我问过a similar question,我认为这可能对你有帮助

标签: python list-comprehension


【解决方案1】:

您可以将其展平

[y if i else x/y for y in range(1, sqrt(x)+1) for i in 0,1 if x%y == 0]

【讨论】:

  • 谢谢,这是完美的。我没有意识到你可以像这样嵌套 for 循环。
【解决方案2】:

您可以分配给元组

[(y, x/y) for y in range(1, int(sqrt(x))+1) if x%y == 0]

与您的基本问题无关,但与您的示例无关:我必须将range() 的第二个参数转换为int,因为sqrt() 在我的测试代码中导致float。

更新在帖子中重新编辑:

要展平这个元组列表:

In [24]: s
Out[24]: [(1, 20), (2, 10), (4, 5)]

使用这个:

In [25]: import operator

创建一个元组:

In [26]: reduce(operator.add, s, ())
Out[26]: (1, 20, 2, 10, 4, 5)

创建一个列表:

In [27]: list(reduce(operator.add, s, ()))
Out[27]: [1, 20, 2, 10, 4, 5]

注意:@jamylak 在有用的评论中指出 reduce 和 operator.add 的运行顺序为 O(N^2),使用 itertools.chain 会更有效率。随着列表大小的增加,这一点变得更加重要,在这种情况下应予以考虑。

【讨论】:

  • @martega 重新编辑:将元组列表展平并不难,请参阅我的更新答案
  • 谢谢,我不知道你能做到这一点:)
  • @Levon 我不喜欢reduce 和operator.add 的这种用法。这是 O(N^2),itertools.chain.from_iterable 会更有效率。
  • @jamylak reduce/add 首先出现在我的脑海中,我敢打赌大多数时候这些列表会足够短,没关系。但是,我明白您的意思,如果您同意,我会将您的评论添加到答案中,以便其他阅读它的人也会考虑它(因为不是每个人都阅读所有 cmets)
  • @Levon 当然可以,你甚至不需要我的同意! :D
【解决方案3】:

是的,你可以做到。您只需要在元素周围加上括号。你得到的是一个元组列表。

>>> [(x, x+1) for x in range(5)]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]

【讨论】:

    【解决方案4】:

    哦,这么近:

    [(y, x/y) for y in range(1, sqrt(x)+1) if x%y == 0]
    

    可以生成一个元组列表,这些当然可以包含多个值。

    【讨论】:

      【解决方案5】:

      绝对可以,只需在值周围使用括号:

      [(y, x/y) for y in range(1, sqrt(x)+1) if x%y == 0]
      

      【讨论】:

        猜你喜欢
        • 2022-01-16
        • 1970-01-01
        • 2012-02-22
        • 2012-08-01
        • 2022-09-23
        • 1970-01-01
        • 1970-01-01
        • 2019-08-24
        • 1970-01-01
        相关资源
        最近更新 更多