【问题标题】:(Set) Comprehension from multiple values(Set) 从多个值中理解
【发布时间】:2017-12-14 01:43:38
【问题描述】:

假设我有一个列表l = [1,2,3],我想创建一个包含该列表中所有数字及其平方的集合。理想情况下,在单个理解表达式中。

我能想到的最好的方法是(对列表进行两次迭代):

set(_ for _ in l).union(_ * _ for _ in l)

【问题讨论】:

  • 它比我认为的嵌套生成器理解更清晰。 BTW,可以简化为{_ for _ in l} | {_ ** 2 for _ in l}
  • @Sraw 这与显式 union() 函数同义,仍然需要对列表进行两次迭代。
  • 我知道,嗯.. 很难解释。有一个答案给出了嵌套生成器的理解,尽管它确实更短,但我看起来很困惑。但现在这个答案已被删除!我写的肯定是同义词,我只想说可以更短更清晰。
  • 其实我找到了解决办法:{*(l + [_ ** 2 for _ in l])}.
  • @Sraw 仍然在 l 上迭代两次 ;-) 看看下面的答案。

标签: python set-comprehension


【解决方案1】:

您自己的代码可以缩短为:

set(l).union(x**2 for x in l)

其中我将_重命名为x,因为_表示该值不重要,但确实重要。

严格来说,您仍在迭代 list 两次,但第一次是隐式的。

如果你坚持迭代一次,你会得到:

{y for x in l for y in (x, x**2)}

这是一个包含以下内容的双重理解:

result = set()
for x in l:
    for y in (x, x**2):
        result.add(y)

【讨论】:

  • 这就是我尝试的那种时髦的双嵌套理解 ?
  • @Jens fors 的顺序总是一个问题。
【解决方案2】:

IMO,set(l + [i ** 2 for i in l]) 是一个更好的解决方案。它比嵌套生成器理解更清晰。

我已经做了一个基准测试:

import timeit
l = list(range(5))
print(timeit.timeit("set(l + [_ ** 2 for _ in l])", 'from __main__ import ' + ', '.join(globals())))
print(timeit.timeit("{y for x in l for y in (x, x**2)}", 'from __main__ import ' + ', '.join(globals())))

输出:

3.0309128219996637
3.1958301850008866

它显示set(l + [i ** 2 for i in l]) 快​​一点。我认为的原因是嵌套生成器理解需要为每个循环创建内部对象(x, x**2),这使得它变慢了。

更新

import timeit
l = list(range(200000))
print(timeit.timeit("set(l + [_ ** 2 for _ in l])", 'from __main__ import ' + ', '.join(globals()), number=100))
print(timeit.timeit("{y for x in l for y in (x, x**2)}", 'from __main__ import ' + ', '.join(globals()), number=100))

输出:

16.46792753900081
19.72252997099895

【讨论】:

  • 对于这么小的列表,结果毫无意义。当它变大时,您首先构建整个列表的事实可能成为一个因素。更有趣的是一个包含 100000 多个元素列表的基准。
  • @ThijsvanDien 已更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 2014-07-21
  • 1970-01-01
  • 2011-03-22
  • 2013-03-10
相关资源
最近更新 更多