检查迭代器是否排序

2024-10-01 00:18:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个迭代器it,我假设它已经排序了,但是如果不是,我想引发一个异常

来自迭代器的数据不在内存中,所以我不想使用sorted()内置函数,因为它会将整个迭代器放在一个列表中。在

我现在使用的解决方案是将迭代器包装在如下生成器函数中:

def checkSorted(it):
  prev_v = it.next()
  yield prev_v
  for v in it:
    if v >= prev_v:
      yield v
      prev_v = v
    else:
      raise ValueError("Iterator is not sorted")

这样我就可以这样使用它:

^{pr2}$

有人知道有没有更好的解决办法?在

我知道我的解决方案是可行的,但独自编写一个模块来完成如此琐碎的任务似乎很奇怪(至少对我来说)。我正在寻找一个简单的一行程序或内置解决方案(如果存在的话)


Tags: 数据函数内存列表for排序defit
2条回答

另外,我建议使用^{}(在python 3中是zip_longest)来创建一个包含连续对的生成器:

可以使用tee从第一个iterable创建2个独立的迭代器。在

from itertools import izip_longest,tee

def checkSorted(it):
  pre,it=tee(it)
  next(it)
  for i,j in izip_longest(pre,it):
    if j:
      if i >= j:         
        yield i
      else:
        raise ValueError("Iterator is not sorted")
    else :
        yield i

演示:

^{pr2}$

注:事实上,我认为你没有必要放弃你所拥有的价值已经。所以作为一种更优雅的方式,我建议在all函数中使用生成器表达式并返回bool值:

from itertools import izip,tee

def checkSorted(it):
  pre,it=tee(it)
  next(it)
  return all(i>=j for i,j in izip(pre,it))

基本上,您的解决方案几乎和它所得到的一样优雅(如果您发现它普遍有用,您当然可以将它放在一个实用模块中)。如果您希望它使用一个无限对象来减少一点代码,您可以这样做,但是您还必须包括一个类定义,它会再次增长代码(除非您内联了类定义):

def checkSorted(it):
    prev = type("", (), {"__lt__": lambda a, b: False})()

    for x in it:
        if prev < x:
            raise ValueError("Not sorted")
        prev = x
        yield x

第一行是使用type首先创建一个类,然后实例化它。此类的对象比任何对象(无穷大对象)都要少。在

执行一行程序的问题是您必须处理三个构造:更新状态(赋值)、抛出异常和执行循环。您可以通过使用语句轻松地执行这些操作,但是将它们变成一个oneliner意味着您将不得不尝试将这些语句放在同一行上—这反过来会导致循环和if-构造出现问题。在

如果你想把整个事情放到一个表达式中,你必须使用肮脏的技巧来完成这些,赋值和循环iterutils可以提供,抛出可以通过使用生成器中的throw方法来完成(它也可以在表达式中提供):

^{pr2}$

最后一个it是要检查的迭代器,表达式的计算结果是已检查的迭代器。我同意它不好看,也不明显它的作用,但你要求它(我不认为你想要它)。在

相关问题 更多 >