【问题标题】:generator vs break in list search生成器与列表搜索中断
【发布时间】:2017-11-24 07:16:47
【问题描述】:

我有一个包含 100 000 个元素的列表,并且我在该列表的末尾有一个元素 4。

在这一点上,这些方法有什么区别?

方法一:

def arr_f():
  for i in arr:
      if i==4:
          yield i
arr=[........100k entries]
gen_ob=arr_f()

for i in gen_ob:
    #do some op

方法二:

def arr_f():
  for i in arr:
      if i==4:
          break
  else:
      return True
  return False

在方法 2 中,我正在等待数字 4 来,如果我击中它就打破循环。在这种情况下,生成器是否比方法 2 有任何优势?

我对生成器的了解是它会即时产生一个值。 就我而言,我的方法 2 存储的元素是否比方法 1 多?

【问题讨论】:

    标签: python list generator


    【解决方案1】:

    在深入比较之前,我将重写您的函数,使其成为纯函数:

    def f1(array, val):
        for i in array:
            if i == val:
                yield i
    
    def f2(array, val):
        for i in array:
            if i == val:
                return False
        
        return True
    

    我假设你的意思是如果值存在则返回False,否则返回True。如果不是,请修正缩进。


    不幸的是,比较 f1f2 没有多大意义,因为它们似乎做不同的事情。一个简单地产生多个版本的val,而另一个只是检查val 是否存在(并且有更简单的方法可以做到这一点)。

    假设4arr 中的最后一个元素,f1(arr, 4)f2(arr, 4) 有什么区别?

    唯一的区别是 f1 返回一个生成器进行迭代,而 f2 返回一个标量 bool 值。


    在一般情况下f1(arr, K)f2(arr, K) 有什么区别,其中Karr 中任何位置存在的任何值?

    f1 在找到K 后不会停止迭代。它将总是继续遍历整个列表。因此,平均、最差和最佳情况复杂度是线性的。

    同时,f2 找到K 的第一个匹配项并相应地返回一个值。由于K 可以在列表中的任何位置,f2 的运行时间取决于您的输入。

    请记住,无论如何,两者都具有最坏情况下的线性复杂性 (O(N))。

    注意f2可以改写为:

    def f2(array, val):
        return val not in array # you could convert to a set, but the conversion is linear, making the subsequent O(1) lookup pointless
    

    【讨论】:

    • 谢谢!所以如果我有一个要搜索的值在列表中只出现一次,比如在列表中间,生成器需要更多时间来执行?因为它也会寻找下一个调用?
    • @syam 是的,因为yield 将导致执行从中断处继续。 return 导致一次性退出,仅此而已。
    • @coldspeed 最后一个问题....通过列表中的所有成员。对吗?
    • @syam 是的,无论哪种方式,您都必须迭代整个事情。使用生成器,您只需将其延迟到实际对其进行迭代(惰性评估)。
    • 太棒了!谢谢!
    猜你喜欢
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 2016-11-27
    • 2021-11-17
    • 2016-10-04
    相关资源
    最近更新 更多