[英]Creating a Python list comprehension with an if and break with nested for loops
我从这个答案中注意到了代码
for i in userInput:
if i in wordsTask:
a = i
break
可以通过以下方式编写为列表推导:
next([i for i in userInput if i in wordsTask])
我有一个类似的问题,我想在列表理解方面编写以下(从原始问题简化)代码:
for i in xrange(N):
point = Point(long_list[i],lat_list[i])
for feature in feature_list:
polygon = shape(feature['geometry'])
if polygon.contains(point):
new_list.append(feature['properties'])
break
我希望每个point
都与要素列表中的单个多边形相关联。 因此,一旦找到包含该点的多边形,则使用break
来移动到下一个点。 因此, new_list
将具有正好N
元素。
我把它写成列表理解如下:
new_list = [feature['properties'] for i in xrange(1000) for feature in feature_list if shape(feature['geometry']).contains(Point(long_list[i],lat_list[i])]
当然,这并没有考虑if
语句中的break
,因此比使用嵌套for循环要花费更长的时间。 使用上面链接的帖子(我可能不完全理解)的建议,我做到了
new_list2 = next(feature['properties'] for i in xrange(1000) for feature in feature_list if shape(feature['geometry']).contains(Point(long_list[i],lat_list[i]))
但是, new_list2
比N个元素少得多(在我的例子中, N=1000
, new_list2
只有5个元素)
问题1:作为列表理解,这甚至值得吗? 唯一的原因是我读到列表理解通常比嵌套for循环快一点。 每秒有200万个数据点。
问题2:如果是这样,我如何在列表理解中加入break
语句?
问题3:以我的方式使用next
出现的错误是什么?
非常感谢你的时间和善意的帮助。
列表推导不一定比for
循环更快。 如果你有一个像这样的模式:
some_var = []
for ...:
if ...:
some_var.append(some_other_var)
然后是的,列表理解比一堆.append()
更快。 但是,你有情有可原的情况。 首先,它实际上是next(...)
的情况下的生成器表达式,因为它没有[
和]
它周围。
.append()
)。 你只是得到一个价值。 xrange(N)
每个i
每个特征调用Point(long_list[i], lat_list[i])
一次,而循环仅为每个i
调用一次。 为什么你的发电机表达不起作用? 因为它只找到整体的第一个值。 另一方面,循环找到每个i
的第一个值。 你看到了区别? 生成器表达式从两个循环中断开,但for
循环仅从内部循环中断开。
如果你想稍微提高性能,可以使用itertools.izip()
(或者只是在Python 3中使用zip()
):
from itertools import izip
for long, lat in izip(long_list, lat_list):
point = Point(long, lat)
...
我不知道复杂的列表推导或生成器表达式比嵌套循环快得多,如果它们运行相同的算法(例如访问相同数量的值)。 为了获得明确的答案,您应该尝试以两种方式实施解决方案并进行测试,以确定哪种方法对您的实际数据更快。
至于如何使内循环短路而不是外循环,你需要将next
调用置于主列表理解中,并在其中包含一个单独的生成器表达式:
new_list = [next(feature['properties'] for feature in feature_list
if shape(feature['shape']).contains(Point(long, lat)))
for long, lat in zip(long_list, lat_list)]
我改变了另外一件事:不是用一个range
索引索引long_list
和lat_list
,而是使用zip
来并行迭代它们。
请注意,如果反复创建Point
对象需要花费太多时间,则可以通过添加另一个嵌套生成器表达式来简化代码的这一部分,该表达式创建点并允许您将它们绑定到(可重用)名称:
new_list = [next(feature['properties'] for feature in feature_list
if shape(feature['shape']).contains(point))
for point in (Point(long, lat) for long, lat in zip(long_list, lat_list))]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.