【问题标题】:Why is "yield" keyword not producing the expected generator in my application? (Merge sort algorithm)为什么“yield”关键字没有在我的应用程序中生成预期的生成器? (归并排序算法)
【发布时间】:2019-12-22 10:23:09
【问题描述】:

为什么我的 yield 关键字没有产生预期的输出?

我正在使用递归算法(合并排序)并使用yield,以便每次更改(排序)列表时都可以遍历列表。

def MergeSort(lst):

    if len(lst) > 1:
        middle = len(lst)//2
        lefthalf = lst[:middle]
        righthalf = lst[middle:]

        MergeSort(lefthalf)
        MergeSort(righthalf)

        i,j,k= 0,0,0

        while i<len(lefthalf) and j<len(righthalf):
            if lefthalf[i] < righthalf[j]:
                lst[k] = lefthalf[i]
                i+=1
            else:
                lst[k] = righthalf[j]
                j+=1

            k+=1

        while i<len(lefthalf):
            lst[k]=lefthalf[i]
            i+=1
            k+=1

        while j<len(righthalf):
            lst[k]=righthalf[j]
            j+=1
            k+=1

        yield lst
a = MergeSort([2,3,566,78,8])
for i in a:
    print(i)
[2, 3, 566, 78, 8]

相反,我希望实现以下目标:(随着算法的工作)

[2, 3, 566, 78, 8]
[2, 3, 566, 8, 78]
[2, 3, 8, 78, 566]

如果我使用return 语句,它将按预期工作并对列表进行排序,但是当我使用yield 时,我无法获得合适的生成器。我还尝试将yield 放在while 语句和其他任何地方。我怎样才能解决这个问题?我错过了什么?

【问题讨论】:

  • 每次调用MergeSort,它只知道它当前正在排序的列表部分,因此它无法为您提供完整列表的“视图”。
  • 你为什么使用yield这个?
  • 我想使用生成器 yield 输出创建动画条形图。

标签: python algorithm generator mergesort yield


【解决方案1】:

因为您将MergeSort 设为生成器,并且生成器是惰性的,所以您的递归调用实际上并没有进行任何排序;他们只是返回生成器,在您迭代它们之前不会做任何工作。你的整个函数也只产生一个列表,因为它只包含一个yield 语句,而且它不在循环中,所以它只执行一次。

解决这两个问题的方法是使用yield from MergeSort(...) 来耗尽您递归创建的生成器。这将耗尽它们以便它们进行排序工作,并且还会导致外部生成器产生内部生成器产生的任何东西。所以,改变这两行:

        yield from MergeSort(lefthalf)
        yield from MergeSort(righthalf)

例子:

>>> for i in MergeSort([2, 3, 566, 78, 8]):
...     print(i)
... 
[2, 3]
[8, 78]
[8, 78, 566]
[2, 3, 8, 78, 566]

请注意,您没有看到相同长度的列表;递归调用在较短的列表上,因此它们产生较短的列表。在基本情况下,您也看不到长度为 1 的列表,因为您的 yield lst 语句位于 if len(lst) &gt; 1: 块内。如果您取消缩进该行以便yield lst 是无条件的,您可以看到每次调用的结果:

>>> for i in MergeSort([2, 3, 566, 78, 8]):
...     print(i)
... 
[2]
[3]
[2, 3]
[566]
[78]
[8]
[8, 78]
[8, 78, 566]
[2, 3, 8, 78, 566]

【讨论】:

  • 非常感谢您帮助我理解这一点。你的解释很完美,使用 yield from 解决了这个问题。非常有用,再次感谢!
猜你喜欢
  • 2011-11-02
  • 1970-01-01
  • 2016-12-02
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
  • 2018-11-04
  • 1970-01-01
相关资源
最近更新 更多