使用另一个python生成器对生成的数字进行排序

Hamidfzm

我正在尝试使用python生成器实现某种合并排序,以在生成的数字中查找最小的数字并生成下一个,这是我的示例代码:

class GeneratorSort():
    def __init__(self, *args):
        self.values = [(arg.next(), i) for i, arg in enumerate(args)]
        self.generators = args

    def generate(self):
        r, index = min(self.values)
        self.values[index] = self.generators[index].next()
        yield r


def t(l):
    for each in l:
        yield each

l1 = [2, 5, 6, 8]
l2 = [1, 4, 5, 7]
l3 = [0, 3, 9, 10]

a = GeneratorSort(t(l1), t(l2), t(l3))

但是,当我尝试打印排序结果时,只有0一次,下次出现错误:

>>> for i in a.generate():
        print i
0

这是错误:

>>> a.generate()
<generator object generate at 0x7fa7bcc37a00>
>>> a.generate().next()

Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    a.generate().next()
  File "/home/hamid/projects/bfl/workspace/testo.py", line 10, in generate
    r, index = min(self.values)
TypeError: 'int' object is not iterable
>>> 

我从这个函数希望打印的数字一样12345和...排序。还有其他办法吗?

请注意,我需要使用发电机。

马丁·彼得斯(Martijn Pieters)

您将只用以下值替换(value, index)元组

self.values[index] = self.generators[index].next()

您需要将其替换为新的元组:

self.values[index] = (self.generators[index].next(), index)

否则,可迭代的分配将失败;您不能将一个分配int给两个变量。

您的生成器缺少一个循环,没有处理空的生成器:

def generate(self):
    while any(self.values):
        r, index = min(v for v in self.values if v)
        try:
            self.values[index] = (self.generators[index].next(), index)
        except StopIteration:
            self.values[index] = None
        yield r

这将设置self.values列表中的元素None以指示可迭代项已用尽。这不是处理这种极端情况的最有效方法。我使用字典跟踪活动的可迭代对象之前编写的一个版本中,只是从该字典中删除以保持索引(键)稳定。

请注意,您可以将t()函数替换为内置iter()函数

演示:

>>> class GeneratorSort():
...     def __init__(self, *args):
...         self.values = [(arg.next(), i) for i, arg in enumerate(args)]
...         self.generators = args
...     def generate(self):
...         while any(self.values):
...             r, index = min(v for v in self.values if v)
...             try:
...                 self.values[index] = (self.generators[index].next(), index)
...             except StopIteration:
...                 self.values[index] = None
...             yield r
... 
>>> l1 = [2, 5, 6, 8]
>>> l2 = [1, 4, 5, 7]
>>> l3 = [0, 3, 9, 10]
>>> a = GeneratorSort(iter(l1), iter(l2), iter(l3))
>>> list(a.generate())
[0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10]

标准库仍然通过heapq.merge()功能更加有效地做到了; 它使用堆以非常有效的方式使可迭代对象按最小值排序;min()需要遍历所有K个可迭代对象,而使用堆仅需执行log-K步即可使堆不变。

>>> import heapq
>>> list(heapq.merge(l1, l2, l3))
[0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10]

您可以研究源代码,该源代码经过了高度优化,以实现最佳性能。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

创建一个生成器,该生成器从任意数量的内部生成器中产生值

Java将md5与来自另一个生成器的另一个md5进行比较:值不相同

enumerate()-在Python中生成一个生成器

如何在另一个生成器函数中访问koa上下文?

如何将一个元组的Python生成器拆分为2个单独的生成器?

通过界面生成器选择另一个故事板

使用新数字之前,Python随机数唯一数字生成器

随机数生成器,每次仅返回一个数字

如何从另一个函数返回生成器

开玩笑:测试生成器函数会产生另一个生成器函数

Python:为什么一个生成器内部比其他生成器快?

Python创建一个生成多个项目的生成器

Laravel查询生成器遇到一个非数字值

将多个无限生成器对象组合到一个生成器中

重复:无法从上下文生成器中的另一个类调用方法

如何根据另一个数组对列表进行排序以在python中生成新数组

如何构建一个简单的令牌生成器

Python生成器返回最后一个项目

需要一个简单的线梯度生成器

使用雄辩的/查询生成器将多个值从一个表插入到另一个表

Symfony 2.7表单生成器具有来自另一个实体的新字段?

如何将值从一个 redux-saga 生成器传递到另一个

运行查询生成器后,原始变量被修改,同时将其分配给另一个变量

如何从一个从另一个生成器中获取每个项目的生成器中产生?

使用另一个生成器的生成器理解

Python,迭代文件或另一个行生成器的函数

为什么生成器列表只返回最后一个生成器的元素?

有没有办法在java中制作一个随机数生成器,它比另一个更有可能落在一个数字上?

需要一个增量器/可迭代器作为另一个生成器 fn 中的变量