假设我有一个列表l = [1,2,3]
,我想在该列表及其正方形中创建一组所有数字。理想情况下,在单一的理解表达中。
我能想到的最好的是(列表上的两次迭代):
set(_ for _ in l).union(_ * _ for _ in l)
答案 0 :(得分:0)
您自己的代码可缩短为:
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)
答案 1 :(得分:0)
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