繁体   English   中英

使用if和break嵌套for循环创建Python列表理解

[英]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=1000new_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_listlat_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM