Thi*_*hib 9 python list-comprehension
假设我有一个元素列表,我想根据某个函数(例如到另一个元素的距离)只选择其中一些元素.
我希望得到一个元组列表,包括距离和元素.所以,我写了下面的代码
result = [ ( myFunction(C), C) for C in originalList if myFunction(C) < limit ]
Run Code Online (Sandbox Code Playgroud)
但这myFunction是一个非常耗时的功能,而且originalList相当大.这样做,myFunction将为每个选定的元素调用两次.
那么,有没有办法避免这种情况?
我还有其他两种可能性,但它们并不是那么好:
第一个是创建未过滤的列表
unfiltered = [ (myFunction(C),C) for C in originalList ]
Run Code Online (Sandbox Code Playgroud)
然后对它进行排序
result = [ (dist,C) for dist,C in unfiltered if dist < limit ]
Run Code Online (Sandbox Code Playgroud)
但在那种情况下,我复制了我
originalList并浪费了一些内存(列表可能非常大 - 超过10,000个元素)
第二个是棘手的,不是非常pythonic,但有效(我们可以做的最好,因为每个元素应该评估一次函数).myFunction将它的最后
结果存储在全局变量中(lastResult例如),并在List comprehension中重用该值
result = [ (lastResult,C) for C in originalList if myFunction(C) < limit ]
Run Code Online (Sandbox Code Playgroud)你是否有更好的想法以高效和pythonic的方式实现这一目标?
谢谢你的回答.
当然,以下两者之间的区别:
[f(x) for x in list]
Run Code Online (Sandbox Code Playgroud)
还有这个:
(f(x) for x in list)
Run Code Online (Sandbox Code Playgroud)
是第一个将在内存中生成列表,而第二个是新生成器,具有惰性求值.
因此,只需将"未过滤"列表作为生成器编写.这是您的代码,生成器内联:
def myFunction(x):
print("called for: " + str(x))
return x * x
originalList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
limit = 10
result = [C2 for C2 in ((myFunction(C), C) for C in originalList) if C2[0] < limit]
# result = [C2 for C2 in [(myFunction(C), C) for C in originalList] if C2[0] < limit]
Run Code Online (Sandbox Code Playgroud)
请注意,您不会看到打印输出与两者的区别,但如果您要查看内存使用情况,则注释掉的第二个语句将使用更多内存.
要在您的问题中对代码进行简单更改,请按原样重写未经过滤的代码:
unfiltered = [ (myFunction(C),C) for C in originalList ]
^ ^
+---------- change these to (..) ---------+
|
v
unfiltered = ( (myFunction(C),C) for C in originalList )
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6237 次 |
| 最近记录: |