【问题标题】:How do I check if a list is sorted? [duplicate]如何检查列表是否已排序? [复制]
【发布时间】:2011-06-10 07:01:39
【问题描述】:

可能重复:
Pythonic way to check if a list is sorted or not

在python中,如何测试一个数字列表是否已经排序?

【问题讨论】:

    标签: python sorting


    【解决方案1】:

    这只能通过迭代列表(隐式或显式)来实现:

    all(b >= a for a, b in zip(the_list, the_list[1:])
    

    但是,如果您需要对它进行排序,为什么不直接对其进行排序呢? Python 的排序算法在已经排序的列表上会非常便宜——可能比上面的测试便宜。

    编辑:因为这变成了关于性能的讨论,所以这里是一个使用惰性迭代器的版本:

    it = iter(the_list)
    it.next()
    all(b >= a for a, b in itertools.izip(the_list, it))
    

    对于具有一百万个条目的随机排序列表,这比 the_list == sorted(the_list) 快 10000 倍以上。

    【讨论】:

    • 确实,这个测试大约是排序时间的两倍。但相比之下,排序后的相等性测试几乎不需要时间,因此some_list == sorted(some_list) 无论如何都是更好的解决方案。
    • 这比随机排序列表快得多。如果您改用itertools.izip,它会更快,尤其是在测试早期短路的情况下。如果您的列表已经处于可预测或预先排序的顺序,排序将会更快,因为 Python 的排序擅长于此,并且此测试不会短路。如果性能确实很重要(OP 没有说它确实如此),那么本机模块当然可以两全其美。
    • @Glenn, @Lennart:这显然没有考虑到大名单上的性能。它使用的额外内存至少是初始列表使用的内存的三倍(在执行zip() 期间;注意the_list[1:] 复制了列表)。为了完整性,我将添加一个使用惰性迭代器的解决方案。
    • 使用 next(it, None) 而不是 it.next() 以避免 StopIteration 异常(空列表是有效的输入(始终排序))。 Micro-nitpick:a <= b 更容易阅读(起初我以为你的代码会检查降序,因为>=)。
    【解决方案2】:
    some_list == sorted(some_list)
    

    【讨论】:

    • 这是不必要的O(n log n) 和非短路。
    • 很抱歉,但这不是最佳答案。当您可以尽早反驳没有订购的东西时,为什么要订购所有东西只是为了比较整套产品?
    【解决方案3】:

    通常您应该已经知道列表是否已排序(因为您的输入是这样定义的,或者您之前已对其进行了排序)。

    如果您需要验证列表是否已排序,因为如果不是,您想对其进行排序,只需对其进行排序。如果列表已经排序,这是一个便宜的操作,并且不会比显式验证顺序贵很多。

    换句话说:

    mylist.sort()
    

    现在你知道它已经排序了。

    【讨论】:

    • 使用一些排序算法,对已经排序的列表进行排序是一项昂贵的操作。不是 Timsort,但显然这是 Python 的一个实现细节。
    • 了解列表是否针对某些问题域进行了排序也很有用 - 您不一定希望对项目进行排序,您只想知道它们是否排序。一个明显的例子是为排序函数编写单元测试。 :)
    【解决方案4】:

    对其他答案的评论多于答案,但这个网站使正确的 cmets 成为不可能。

    如果列表已经部分或完全排序,排序解决方案会更快。如果列表可能是随机顺序的,或者如果列表在早期是无序的,则迭代解决方案会更快。

    这有两个原因。首先,当 Python 以它理解的顺序(部分排序、反转等)给定数据时,它的排序非常好,但如果数据是随机的或不可预测的,那么它不会比任何其他排序做得更好。其次,如果迭代解决方案很早就发现列表未排序,则它可能会短路几乎没有工作。

    这显示了相反的极端:

    import timeit, random, itertools
    
    def a(data):
        return all(b >= a for a, b in itertools.izip(data, itertools.islice(data, 1, None)))
    
    def b(data):
        return data == sorted(data)
    
    def main():
        data = range(1000000)
        print "Sorted, iterative:", timeit.timeit(lambda: a(data), number=10)
        print "Sorted, sort:", timeit.timeit(lambda: b(data), number=10)
    
        random.shuffle(data)
        print "Random, iterative:", timeit.timeit(lambda: a(data), number=10)
        print "Random, sort:", timeit.timeit(lambda: b(data), number=10)
    

    导致我的系统出现这些时间:

    Sorted, iterative: 1.42838597298
    Sorted, sort: 0.498414993286
    Random, iterative: 0.000043
    Random, sort: 10.5548219681
    

    因此,在这些极端情况下,排序方法大约快三倍,而线性方法大约快...二十万倍。

    注意这里真正的区别是不是 O(n) vs. O(n log n);这些复杂性之间的差异并没有那么大。主要区别在于,线性版本一旦发现两个乱序的值就会短路,而排序版本总是必须完成所有工作。

    本机实现可以同时获得理想的性能,提供 O(n) 复杂度、短路能力以及本机代码的低开销,从而使排序方法更快。如果(且仅当!)性能真的很重要,那将是正确的解决方案。

    (请注意,除非性能实际上是一个问题,否则我通常不建议根据性能选择解决方案,但这里值得注意的是,这两种方法都没有比另一种简单得多。排序版本更容易理解,但迭代版本也没有什么复杂的。)

    【讨论】:

    • +1 表示最后一段。如果性能很重要,那么显式循环 for a, b in izip(data,islice(data, 1, None)):if a > b: return Falseall() 变体快约 50%。
    【解决方案5】:
    if L == (lambda pp=[]: reduce(lambda p, i: pp.append(reduce(lambda t, i:
            (lambda t, i, j: (lambda l=[]: map(lambda x: (lambda xx=l.append(1):
            t[sum(l) - 1] if sum(l) not in map(1..__radd__, (i, j)) else (t[i] if
            sum(l) == j + 1 else t[j]))(), t))())(t, i, i + 1) if t[i] >= t[i + 1]
            else t, xrange(len(p) - 1), p)) or pp[-1], iter(lambda: len(pp) >= 2
            and list.__eq__(*pp[-2:]), True), L))():
        print "yeah, it's sorted"
    

    【讨论】:

    • 什么!?这有什么帮助?这不是单线比赛。在其中添加一些新行和一些 cmets,您将拥有世界其他地方不会介意阅读的代码。
    • @J.F. Sebastian,如果不清楚,我的代码会对相关列表进行冒泡排序,然后检查结果是否等于原始列表。
    • 保证对试图了解其真正工作原理的人造成脑损伤。带调试器的意外之旅更有趣!而且我希望看看小组中其他开发人员在他们可爱的 IDE 中打开代码然后看到这个 :))) 的脸。我猜他们会用 bat 追踪此类代码的作者 :)
    • 投反对票,因为这段代码很难理解。 SO 应提供仅在必要时尽可能复杂的答案。另见 Python 之禅,#4:“复杂胜于复杂。”。
    • @user465139 我认为这复杂的,而不是复杂的。所以,我想我们同意?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-17
    • 2020-08-20
    • 2012-02-05
    • 2012-07-20
    • 2011-04-14
    • 1970-01-01
    相关资源
    最近更新 更多