[python] 목록이 정렬되었는지 여부를 확인하는 Pythonic 방법

목록이 이미 정렬되어 있는지 확인하는 파이썬 방법이 ASC또는DESC

listtimestamps = [1, 2, 3, 5, 6, 7]

같은 isttimestamps.isSorted()그 반환 True또는 False.

일부 메시지의 타임 스탬프 목록을 입력하고 트랜잭션이 올바른 순서로 나타나는지 확인하고 싶습니다.



답변

실제로 우리는 anijhaw가 찾고있는 해답을주지 않습니다. 하나의 라이너는 다음과 같습니다.

all(l[i] <= l[i+1] for i in xrange(len(l)-1))

파이썬 3의 경우 :

all(l[i] <= l[i+1] for i in range(len(l)-1))


답변

난 그냥 사용할거야

if sorted(lst) == lst:
    # code here

매우 큰 목록이 아닌 경우 사용자 정의 함수를 만들 수 있습니다.

정렬되지 않은 경우 정렬하려는 경우 확인을 잊고 정렬하십시오.

lst.sort()

그것에 대해 너무 많이 생각하지 마십시오.

사용자 정의 기능을 원하면 다음과 같은 작업을 수행 할 수 있습니다

def is_sorted(lst, key=lambda x: x):
    for i, el in enumerate(lst[1:]):
        if key(el) < key(lst[i]): # i is the index of the previous element
            return False
    return True

목록이 이미 정렬되어 있으면 for루프 (O (n) 입니다!)이므로 대부분 정렬되지 않을 것으로 예상하지 않는 한, 다시 목록을 정렬하십시오.


답변

이 반복자 형식은 정수 색인 작성보다 10-15 % 빠릅니다.

# python2 only
if str is bytes:
    from itertools import izip as zip

def is_sorted(l):
    return all(a <= b for a, b in zip(l, l[1:]))


답변

이것을 구현하는 아름다운 방법 imapitertools다음 에서 함수 를 사용하는 것입니다 .

from itertools import imap, tee
import operator

def is_sorted(iterable, compare=operator.le):
  a, b = tee(iterable)
  next(b, None)
  return all(imap(compare, a, b))

이 구현은 빠르며 모든 iterable에서 작동합니다.


답변

나는 벤치 마크를 실행 하고 sorted(lst, reverse=True) == lst긴 목록에 대한 가장 빠른, 그리고 all(l[i] >= l[i+1] for i in xrange(len(l)-1))가장 빠른 짧은 목록에 대한이었다 . 이 벤치 마크는 MacBook Pro 2010 13 “(Core2 Duo 2.66GHz, 4GB 1067MHz DDR3 RAM, Mac OS X 10.6.5)에서 실행되었습니다.

업데이트 : 스크립트를 수정하여 자신의 시스템에서 직접 실행할 수 있습니다. 이전 버전에는 버그가있었습니다. 또한 정렬 된 입력과 정렬되지 않은 입력을 모두 추가했습니다.

  • 짧은 정렬 목록에 가장 적합 : all(l[i] >= l[i+1] for i in xrange(len(l)-1))
  • 긴 정렬 목록에 가장 적합 : sorted(l, reverse=True) == l
  • 분류되지 않은 짧은 목록에 가장 적합 : all(l[i] >= l[i+1] for i in xrange(len(l)-1))
  • 정렬되지 않은 긴 목록에 가장 적합 : all(l[i] >= l[i+1] for i in xrange(len(l)-1))

따라서 대부분의 경우 확실한 승자가 있습니다.

업데이트 : aaronsterling의 답변 (# 6 및 # 7)은 실제로 모든 경우에서 가장 빠릅니다. # 7은 키를 조회 할 수있는 간접 계층이 없기 때문에 가장 빠릅니다.

#!/usr/bin/env python

import itertools
import time

def benchmark(f, *args):
    t1 = time.time()
    for i in xrange(1000000):
        f(*args)
    t2 = time.time()
    return t2-t1

L1 = range(4, 0, -1)
L2 = range(100, 0, -1)
L3 = range(0, 4)
L4 = range(0, 100)

# 1.
def isNonIncreasing(l, key=lambda x,y: x >= y):
    return all(key(l[i],l[i+1]) for i in xrange(len(l)-1))
print benchmark(isNonIncreasing, L1) # 2.47253704071
print benchmark(isNonIncreasing, L2) # 34.5398209095
print benchmark(isNonIncreasing, L3) # 2.1916718483
print benchmark(isNonIncreasing, L4) # 2.19576501846

# 2.
def isNonIncreasing(l):
    return all(l[i] >= l[i+1] for i in xrange(len(l)-1))
print benchmark(isNonIncreasing, L1) # 1.86919999123
print benchmark(isNonIncreasing, L2) # 21.8603689671
print benchmark(isNonIncreasing, L3) # 1.95684289932
print benchmark(isNonIncreasing, L4) # 1.95272517204

# 3.
def isNonIncreasing(l, key=lambda x,y: x >= y):
    return all(key(a,b) for (a,b) in itertools.izip(l[:-1],l[1:]))
print benchmark(isNonIncreasing, L1) # 2.65468883514
print benchmark(isNonIncreasing, L2) # 29.7504849434
print benchmark(isNonIncreasing, L3) # 2.78062295914
print benchmark(isNonIncreasing, L4) # 3.73436689377

# 4.
def isNonIncreasing(l):
    return all(a >= b for (a,b) in itertools.izip(l[:-1],l[1:]))
print benchmark(isNonIncreasing, L1) # 2.06947803497
print benchmark(isNonIncreasing, L2) # 15.6351969242
print benchmark(isNonIncreasing, L3) # 2.45671010017
print benchmark(isNonIncreasing, L4) # 3.48461818695

# 5.
def isNonIncreasing(l):
    return sorted(l, reverse=True) == l
print benchmark(isNonIncreasing, L1) # 2.01579380035
print benchmark(isNonIncreasing, L2) # 5.44593787193
print benchmark(isNonIncreasing, L3) # 2.01813793182
print benchmark(isNonIncreasing, L4) # 4.97615599632

# 6.
def isNonIncreasing(l, key=lambda x, y: x >= y):
    for i, el in enumerate(l[1:]):
        if key(el, l[i-1]):
            return False
    return True
print benchmark(isNonIncreasing, L1) # 1.06842684746
print benchmark(isNonIncreasing, L2) # 1.67291283607
print benchmark(isNonIncreasing, L3) # 1.39491200447
print benchmark(isNonIncreasing, L4) # 1.80557894707

# 7.
def isNonIncreasing(l):
    for i, el in enumerate(l[1:]):
        if el >= l[i-1]:
            return False
    return True
print benchmark(isNonIncreasing, L1) # 0.883186101913
print benchmark(isNonIncreasing, L2) # 1.42852401733
print benchmark(isNonIncreasing, L3) # 1.09229516983
print benchmark(isNonIncreasing, L4) # 1.59502696991


답변

나는 이것을 할 것입니다 ([Aaron Sterling, Wai Yip Tung, Paul McGuire의 일종 ) 및 대부분 Armin Ronacher )

from itertools import tee, izip

def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

def is_sorted(iterable, key=lambda a, b: a <= b):
    return all(key(a, b) for a, b in pairwise(iterable))

한 가지 좋은 점은 시리즈에 대해 두 번째 반복 가능을 구현할 필요가 없다는 것입니다 (목록 조각과는 달리).


답변

numpy.diff ()를 기반으로 한이 라이너를 사용합니다.

def issorted(x):
    """Check if x is sorted"""
    return (numpy.diff(x) >= 0).all() # is diff between all consecutive entries >= 0?

나는 다른 방법에 대해 실제로 시간을 정하지 않았지만 numpy.diff의 루프가 아마도 C (n-1 빼기 다음에 n이 있기 때문에) 특히 순수한 n에 대해 순수한 파이썬 방법보다 빠르다고 가정합니다. -1 비교).

그러나 x가 부호없는 int 인 경우주의해야합니다. 이로 인해 numpy.diff ()에서 자동 정수 언더 플로가 발생하여 오 탐지가 발생할 수 있습니다. 수정 된 버전은 다음과 같습니다.

def issorted(x):
    """Check if x is sorted"""
    try:
        if x.dtype.kind == 'u':
            # x is unsigned int array, risk of int underflow in np.diff
            x = numpy.int64(x)
    except AttributeError:
        pass # no dtype, not an array
    return (numpy.diff(x) >= 0).all()