วิธี Pythonic เพื่อตรวจสอบว่ารายการเรียงลำดับหรือไม่


145

มีวิธี pythonic เพื่อตรวจสอบว่ารายการเรียงแล้วASCหรือDESC

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

สิ่งที่ต้องการisttimestamps.isSorted()ผลตอบแทนที่หรือTrueFalse

ฉันต้องการที่จะป้อนรายการของการประทับเวลาสำหรับข้อความบางส่วนและตรวจสอบว่าการทำธุรกรรมที่ปรากฏในลำดับที่ถูกต้อง

คำตอบ:


212

ที่จริงแล้วเราไม่ได้ให้คำตอบที่อนิหาจกำลังมองหา นี่คือหนึ่งซับ:

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

สำหรับ Python 3:

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

2
ดีจัง คุณอาจต้องการห่อในฟังก์ชั่นเพื่อให้คุณสามารถส่งผ่านkeyฟังก์ชั่นที่จะใช้ key=lambda x, y: x < yทำให้เป็นค่าเริ่มต้นที่ดี
aaronasterling

3
คำสั่งผสมของคำตอบสองสามข้อ:def isSorted(x, key = lambda x: x): return all([key(x[i]) <= key(x[i + 1]) for i in xrange(len(x) - 1)])
eacousineau

2
@aaronasterling: operator.leควรจะเร็วกว่าแลมบ์ดา
แมเรียน

สิ่งนี้ไม่ได้ผลสำหรับฉัน (python --version = 2.6.4) l = [1, 2, 3, 4, 1, 6, 7, 8, 7] all(l[i] <= l[i+1] for i in xrange(len(l)-1)) พิมพ์เป็นผลลัพธ์:True
prodev_paris

1
ดูเหมือนว่างูหลาม 3.x ไม่ได้อีกต่อไปเพียงแค่ใช้xrange rangeฉันได้รับNameError: name 'xrange' is not definedเมื่อฉันเรียกใช้รหัสนั้น ฉันเปลี่ยนเป็นใช้rangeแทนxrangeและใช้งานได้ดี ดู: stackoverflow.com/questions/15014310/…
Cale Sweeney

78

ฉันจะใช้

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

นี่จะเป็น O (n) หากมีการเรียงลำดับรายการแล้ว (และ O (n) ในforลูปที่!) ดังนั้นหากคุณคาดว่าจะไม่เรียงลำดับ (และสุ่มค่อนข้าง) ส่วนใหญ่ฉันจะ อีกครั้งเพียงเรียงลำดับรายการ


10
ถ้านั่นคือสิ่งที่คุณกำลังจะทำคุณก็อาจจะพูดว่า: lst.sort () โดยไม่มีการตรวจสอบเงื่อนไข ;-)
SapphireSun

5
นั่นคือสิ่งที่ถูกต้องมีวิธีที่เร็วกว่าอย่างชัดเจนใน O (n) โดยใช้การวนรอบแบบง่าย
anijhaw

1
@SapphireSun นั่นคือสิ่งที่ฉันพูด;)
aaronasterling

@anijhaw, ดูการอัปเดตที่ฉันทำในขณะที่คุณแสดงความคิดเห็น การตรวจสอบคือ O (n) และการเรียงลำดับคือ O (nlgn) จะดีกว่าไหมถ้ามีค่าใช้จ่าย O (n) เพียงแค่หมุนไปรอบ ๆ และเพิ่ม O (nlgn) หรือใช้ค่าใช้จ่ายในการเรียงลำดับรายการที่เรียงลำดับซึ่ง (ฉันเชื่อว่า) O (n) สำหรับ timsort
aaronasterling

@ แอรอน: ตรวจสอบแก้ไขเพื่อคำถามเดิม
anijhaw

44

แบบฟอร์มตัววนซ้ำนี้เร็วกว่าการใช้การทำดัชนีจำนวนเต็ม 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:]))

ฉันไม่เห็นความแตกต่างอย่างมีนัยสำคัญในเครื่องของฉันgist.github.com/735259ตัวแปร # 7 ที่ดัดแปลงมาจากคำตอบของ @Nathan Farrington คือ 2x stackoverflow.com/questions/3755136/…
jfs

สิ่งนี้จะใช้ได้กับคอนเทนเนอร์ 'ที่จัดทำดัชนีได้' เช่นรายการเท่านั้นในกรณีนี้จะมีการสร้างรายการใหม่สองรายการด้วยการแบ่งส่วน สำหรับ iterators ทั่วไปฉันชอบวิธีการแก้ปัญหาของ Alexandre
Bas Swinckels

1
คำตอบที่สง่างามคุณสามารถใช้izipและisliceจาก itertools เพื่อให้เร็วขึ้น
Elmex80s

@jfs: "ตัวแปร # 7 จาก Nathan Farrington" ผิด มันไม่ได้ทำในสิ่งที่ควรทำและนั่นคือสาเหตุที่มันเร็วกว่า ดูความคิดเห็นของฉันที่นั่น
olivecoder

1
คุณสามารถทำให้โซลูชันของคุณง่ายขึ้นเพื่อ zip (l, l [1:]) เนื่องจาก zip จะหยุดเมื่ออาร์กิวเมนต์ที่สั้นที่สุดหมดลง
Gelineau

20

วิธีที่สวยงามในการใช้งานนี้คือการใช้imapฟังก์ชั่นจากitertools:

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))

การใช้งานนี้รวดเร็วและทำงานบน iterables ใด ๆ


4
ดี แต่มีข้อผิดพลาด! ลองใช้is_sorted(iter([1,2,3,2,5,8]))หรือเครื่องกำเนิดไฟฟ้าที่เทียบเท่า คุณจำเป็นต้องใช้ iterator อิสระtail, itertools.teeลอง
Kos

โปรดจำไว้ว่าiter(x) is xสำหรับตัววนซ้ำ
Kos

1
อานั่นเป็นเรื่องประหลาดใจที่ไม่พึงประสงค์! ฉันซ่อมมันแล้ว ขอบคุณ!
Alexandre Vassalotti

3
โปรดทราบว่าในหลาม 3 ได้รับการเปลี่ยนชื่อเป็นitertools.imap [__builtins__.]map
Nick T

10

ฉันวิ่งมาตรฐานและ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

1
คุณกำลังทำการทดสอบกรณีที่แย่ที่สุดสำหรับแบบฟอร์มนิพจน์ตัวสร้างและกรณีที่ดีที่สุดสำหรับโซลูชันของฉัน คุณอาจต้องการทดสอบกับรายการที่ไม่เรียงลำดับเช่นกัน จากนั้นคุณจะเห็นว่าถ้าคุณคาดว่ารายการจะเรียงลำดับส่วนใหญ่นิพจน์ตัวสร้างจะดีกว่า
aaronasterling

@Aaronsterling ฉันได้อัปเดตสคริปต์เพื่อให้มีทั้งอินพุตและเรียงลำดับที่ไม่เรียงลำดับ
Nathan Farrington

ฟังก์ชั่นทั้งหมดที่enumerateมีไม่ถูกต้อง enumerate(l[1:])ควรถูกแทนที่ด้วยenumerate(l[1:], 1)
jfs

1
แทนการแทนที่enumerate(l[1:])โดยenumerate(l[1:], 1)คุณสามารถแทนที่โดยl[i-1] l[i]
jfs

หากคุณเพิ่มการป้อนข้อมูลแบบสุ่มเช่นL5=range(100); random.shuffle(L5)# 5 นั้นค่อนข้างช้า ในกรณีนี้การแก้ไข # 7 จะเร็วขึ้นโดยรวมcodepad.org/xmWPxHQY
jfs

9

ฉันจะทำสิ่งนี้ (ขโมยคำตอบมากมายที่นี่ [Aaron Sterling, Wai Yip Tung, sorta จาก 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))

สิ่งหนึ่งที่ดี: คุณไม่จำเป็นต้องตระหนักถึง iterable ตัวที่สองของซีรียส์


2
keyชื่อที่ทำให้เข้าใจผิด keyควรใช้เพื่อเปลี่ยนรายการเป็นค่าที่เปรียบเทียบได้
InQβ

4

ฉันใช้สายการบินเดียวโดยใช้ numpy.diff ():

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

ฉันยังไม่ได้ตั้งเวลากับวิธีอื่น ๆ แต่ฉันคิดว่ามันเร็วกว่าวิธี Python บริสุทธิ์โดยเฉพาะอย่างยิ่งสำหรับ n ขนาดใหญ่เนื่องจากการวนซ้ำใน numpy.diff (อาจ) ทำงานโดยตรงในการลบ C (n-1 ตามด้วย 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()

4

นี่คล้ายกับคำตอบยอดนิยม แต่ฉันชอบดีกว่าเพราะหลีกเลี่ยงการทำดัชนีอย่างชัดเจน สมมติว่ารายการของคุณมีชื่อlstคุณสามารถสร้างสิ่ง
(item, next_item)อันดับจากรายการของคุณด้วยzip:

all(x <= y for x,y in zip(lst, lst[1:]))

ใน Python 3 zipส่งคืนตัวสร้างแล้วใน Python 2 ที่คุณสามารถใช้ได้itertools.izipเพื่อประสิทธิภาพหน่วยความจำที่ดีขึ้น

การสาธิตขนาดเล็ก:

>>> lst = [1, 2, 3, 4]
>>> zip(lst, lst[1:])
[(1, 2), (2, 3), (3, 4)]
>>> all(x <= y for x,y in zip(lst, lst[1:]))
True
>>> 
>>> lst = [1, 2, 3, 2]
>>> zip(lst, lst[1:])
[(1, 2), (2, 3), (3, 2)]
>>> all(x <= y for x,y in zip(lst, lst[1:]))
False

อันสุดท้ายล้มเหลวเมื่อทูเปิล (3, 2)ประเมินค่า

โบนัส: ตรวจสอบเครื่องกำเนิดไฟฟ้า จำกัด (!) ซึ่งไม่สามารถจัดทำดัชนีได้:

>>> def gen1():
...     yield 1
...     yield 2
...     yield 3
...     yield 4
...     
>>> def gen2():
...     yield 1
...     yield 2
...     yield 4
...     yield 3
... 
>>> g1_1 = gen1()
>>> g1_2 = gen1()
>>> next(g1_2)
1
>>> all(x <= y for x,y in zip(g1_1, g1_2))
True
>>>
>>> g2_1 = gen2()
>>> g2_2 = gen2()
>>> next(g2_2)
1
>>> all(x <= y for x,y in zip(g2_1, g2_2))
False

ตรวจสอบให้แน่ใจว่าใช้itertools.izipที่นี่หากคุณใช้ Python 2 ไม่เช่นนั้นคุณจะเอาชนะวัตถุประสงค์ที่ไม่ต้องสร้างรายการจากเครื่องกำเนิดไฟฟ้า


2
คุณสามารถใช้isliceเพื่อปรับให้เหมาะสมสำหรับการแบ่งส่วน นอกจากนี้ในโมดูล itertools all(x <= y for x, y in izip(lst, islice(lst, 1))).
Elmex80s

3

แซฟไฟร์ซันค่อนข้างถูกต้อง lst.sort()คุณก็สามารถใช้ การดำเนินการเรียงลำดับของ Python (TimSort) ตรวจสอบว่ารายการเรียงลำดับแล้ว ถ้าเรียงลำดับ () จะเสร็จสมบูรณ์ในเวลาเชิงเส้น เสียงเหมือนวิธี Pythonic เพื่อให้มั่นใจว่ารายการเรียงลำดับแล้ว)


20
เฉพาะเวลาเชิงเส้นหากเรียงตามจริงแล้วเรียงลำดับ หากไม่มีการลัดวงจรเพื่อข้ามภารกิจการเรียงลำดับที่แท้จริงดังนั้นอาจเป็นการลงโทษที่ใหญ่มากหากรายการนั้นยาว
PaulMcG

นี่คือคำตอบที่ดีถ้างานของคุณคือ "ให้แน่ใจว่ารายการนั้นเรียงลำดับแล้วตายถ้าไม่ใช่" ซึ่งเป็นเรื่องธรรมดาเหมือนการตรวจสุขภาพข้อมูลที่ควรเรียงด้วยเหตุผลอื่น จากนั้นเฉพาะกรณีข้อผิดพลาดจะช้า
Ed Avis

3

แม้ว่าฉันไม่คิดว่าจะมีการรับประกันว่าการsortedเรียกใช้ฟังก์ชัน cmp ในตัวi+1, iแต่ดูเหมือนว่าจะเป็นเช่นนั้นสำหรับ CPython

ดังนั้นคุณสามารถทำสิ่งที่ชอบ:

def my_cmp(x, y):
   cmpval = cmp(x, y)
   if cmpval < 0:
      raise ValueError
   return cmpval

def is_sorted(lst):
   try:
      sorted(lst, cmp=my_cmp)
      return True
   except ValueError:
      return False

print is_sorted([1,2,3,5,6,7])
print is_sorted([1,2,5,3,6,7])

หรือด้วยวิธีนี้ (โดยไม่มีถ้าข้อความ -> EAFP ผิดพลาด? ;-)):

def my_cmp(x, y):
   assert(x >= y)
   return -1

def is_sorted(lst):
   try:
      sorted(lst, cmp=my_cmp)
      return True
   except AssertionError:
      return False

3

ไม่ได้เป็น Pythonic มากนัก แต่เราต้องการreduce()คำตอบอย่างน้อยหนึ่งข้อใช่ไหม

def is_sorted(iterable):
    prev_or_inf = lambda prev, i: i if prev <= i else float('inf')
    return reduce(prev_or_inf, iterable, float('-inf')) < float('inf')

ตัวแปรตัวสะสมเก็บเพียงค่าที่ตรวจสอบล่าสุดและหากค่าใด ๆ มีค่าน้อยกว่าค่าก่อนหน้าตัวสะสมจะถูกตั้งค่าเป็นอนันต์ (และจะยังคงเป็นค่าสิ้นสุดในตอนท้ายเนื่องจาก 'ค่าก่อนหน้า' จะใหญ่กว่าเสมอ ปัจจุบัน)


2

ตามที่ระบุไว้โดย @aaronsterling วิธีแก้ปัญหาต่อไปนี้สั้นที่สุดและดูเหมือนเร็วที่สุดเมื่อเรียงลำดับและไม่เล็กเกินไป: def is_sorted (lst): return (เรียงลำดับ (lst) == lst)

หากเวลาส่วนใหญ่ไม่ได้เรียงลำดับอาเรย์จะเป็นที่พึงปรารถนาที่จะใช้โซลูชันที่ไม่สแกนอาเรย์ทั้งหมดและส่งคืนค่า False ทันทีที่ค้นพบคำนำหน้าที่ไม่เรียงลำดับ ต่อไปนี้เป็นวิธีแก้ปัญหาที่เร็วที่สุดที่ฉันสามารถหาได้

def is_sorted(lst):
    it = iter(lst)
    try:
        prev = it.next()
    except StopIteration:
        return True
    for x in it:
        if prev > x:
            return False
        prev = x
    return True

การใช้เกณฑ์มาตรฐานของ Nathan Farrington ทำให้สามารถรันไทม์ได้ดีกว่าการใช้ sort (lst) ในทุกกรณียกเว้นเมื่อทำงานในรายการที่เรียงลำดับขนาดใหญ่

นี่คือผลลัพธ์มาตรฐานในคอมพิวเตอร์ของฉัน

เรียงลำดับ (lst) == lst solution

  • L1: 1.23838591576
  • L2: 4.19063091278
  • L3: 1.17996287346
  • L4: 4.68399500847

ทางออกที่สอง:

  • L1: 0.81095790863
  • L2: 0.802397012711
  • L3: 1.06135106087
  • L4: 8.82761001587

2

ถ้าคุณต้องการวิธีที่เร็วที่สุดสำหรับอาร์เรย์ numpy ให้ใช้numbaซึ่งหากคุณใช้ conda ควรได้รับการติดตั้งแล้ว

รหัสจะเร็วเพราะจะถูกคอมไพล์โดย numba

import numba
@numba.jit
def issorted(vec, ascending=True):
    if len(vec) < 2:
        return True
    if ascending:
        for i in range(1, len(vec)):
            if vec[i-1] > vec[i]:
                return False
        return True
    else:
        for i in range(1, len(vec)):
            if vec[i-1] < vec[i]:
                return False
        return True

แล้ว:

>>> issorted(array([4,9,100]))
>>> True

2

เพียงเพิ่มวิธีอื่น (แม้ว่าต้องใช้โมดูลเพิ่มเติม) iteration_utilities.all_monotone::

>>> from iteration_utilities import all_monotone
>>> listtimestamps = [1, 2, 3, 5, 6, 7]
>>> all_monotone(listtimestamps)
True

>>> all_monotone([1,2,1])
False

วิธีตรวจสอบคำสั่ง DESC:

>>> all_monotone(listtimestamps, decreasing=True)
False

>>> all_monotone([3,2,1], decreasing=True)
True

นอกจากนี้ยังมีstrictพารามิเตอร์หากคุณต้องการตรวจสอบอย่างเคร่งครัด (หากองค์ประกอบที่ต่อเนื่องไม่ควรเท่ากัน) ลำดับแบบโมโนโทนิก

มันไม่ใช่ปัญหาในกรณีของคุณ แต่ถ้าลำดับของคุณมีnanค่าวิธีการบางอย่างจะล้มเหลวตัวอย่างเช่นเรียงลำดับ:

def is_sorted_using_sorted(iterable):
    return sorted(iterable) == iterable

>>> is_sorted_using_sorted([3, float('nan'), 1])  # definetly False, right?
True

>>> all_monotone([3, float('nan'), 1])
False

โปรดทราบว่าiteration_utilities.all_monotoneทำงานได้เร็วขึ้นเมื่อเทียบกับโซลูชันอื่น ๆ ที่กล่าวถึงที่นี่โดยเฉพาะอย่างยิ่งสำหรับอินพุตที่ไม่ได้เรียงลำดับ (ดูมาตรฐาน )


2

ขี้เกียจ

from itertools import tee

def is_sorted(l):
    l1, l2 = tee(l)
    next(l2, None)
    return all(a <= b for a, b in zip(l1, l2))

1
Absolutelly สุดยอด! นี่คือการปรับปรุงของฉันที่จะทำให้มันเป็นหนึ่งซับ - แทน iter () และถัดไป () ใช้การแบ่งส่วนด้วยผลลัพธ์เดียวกัน:all(a <= b for a, b in zip(l, l[1:]))
Matt

1
@LiborJelinek ดี แต่รุ่นของฉันทำงานเมื่อlเป็นตัวสร้างและไม่รองรับการแบ่งส่วน
Sergey11g

2

Python 3.6.8

from more_itertools import pairwise

class AssertionHelper:
    @classmethod
    def is_ascending(cls, data: iter) -> bool:
        for a, b in pairwise(data):
            if a > b:
                return False
        return True

    @classmethod
    def is_descending(cls, data: iter) -> bool:
        for a, b in pairwise(data):
            if a < b:
                return False
        return True

    @classmethod
    def is_sorted(cls, data: iter) -> bool:
        return cls.is_ascending(data) or cls.is_descending(data)
>>> AssertionHelper.is_descending((1, 2, 3, 4))
False
>>> AssertionHelper.is_ascending((1, 2, 3, 4))
True
>>> AssertionHelper.is_sorted((1, 2, 3, 4))
True

0

วิธีที่ง่ายที่สุด:

def isSorted(arr):
  i = 1
  while i < len(arr):
    if(result[i] < result[i - 1]):
      return False
    i += 1
  return True

0
from functools import reduce

# myiterable can be of any iterable type (including list)
isSorted = reduce(lambda r, e: (r[0] and (r[1] or r[2] <= e), False, e), myiterable, (True, True, None))[0]

ค่าการลดที่ได้รับคือ tuple 3 ส่วนของ ( sortSoFarFlag , firstTimeFlag , lastElementValue ) ตอนแรกมันเริ่มต้นด้วย ( True, True, None) ซึ่งถูกนำมาใช้เป็นผลสำหรับรายการที่ว่างเปล่า (การยกย่องว่าเป็นเรียงเพราะไม่มีออกจากการสั่งซื้อองค์ประกอบ) เมื่อประมวลผลแต่ละองค์ประกอบจะคำนวณค่าใหม่สำหรับ tuple (โดยใช้ค่า tuple ก่อนหน้ากับ elementValue ถัดไป):

[0] (sortedSoFarFlag) evaluates true if: prev_0 is true and (prev_1 is true or prev_2 <= elementValue)
[1] (firstTimeFlag): False
[2] (lastElementValue): elementValue

ผลลัพธ์สุดท้ายของการลดคือ tuple ของ:

[0]: True/False depending on whether the entire list was in sorted order
[1]: True/False depending on whether the list was empty
[2]: the last element value

ค่าแรกคือค่าที่เราสนใจดังนั้นเราใช้[0]เพื่อคว้าค่านั้นจากผลลัพธ์ที่ลดลง


โปรดทราบว่าโซลูชันนี้ทำงานได้ทุกประเภทที่มี iterable ที่สามารถเปรียบเทียบกันได้ ที่มีรายการบูลีน (ตรวจสอบค่าเท็จเกิดขึ้นก่อนค่า True), รายการตัวเลข, รายการสตริง (เรียงตามตัวอักษร), รายการชุด (เซตย่อยเกิดขึ้นก่อน supersets) เป็นต้น
Mr Weasel

0

เนื่องจากฉันไม่เห็นตัวเลือกนี้ด้านบนฉันจะเพิ่มไปยังคำตอบทั้งหมด ให้แสดงรายการโดยlแล้ว:

import numpy as np

# Trasform the list to a numpy array
x = np.array(l)

# check if ascendent sorted:
all(x[:-1] <= x[1:])

# check if descendent sorted:
all(x[:-1] >= x[1:])

0

โซลูชันที่ใช้นิพจน์การมอบหมาย (เพิ่มใน Python 3.8):

def is_sorted(seq):
    seq_iter = iter(seq)
    cur = next(seq_iter, None)
    return all((prev := cur) <= (cur := nxt) for nxt in seq_iter)

z = list(range(10))
print(z)
print(is_sorted(z))

import random
random.shuffle(z)
print(z)
print(is_sorted(z))

z = []
print(z)
print(is_sorted(z))

ให้:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
True
[1, 7, 5, 9, 4, 0, 8, 3, 2, 6]
False
[]
True

-1

อันที่จริงแล้ววิธีที่สั้นที่สุดในการใช้การเรียกซ้ำ:

ถ้ามันเรียงแล้วจะพิมพ์จริงจะพิมพ์ออกมาเท็จ

 def is_Sorted(lst):
    if len(lst) == 1:
       return True
    return lst[0] <= lst[1] and is_Sorted(lst[1:])

 any_list = [1,2,3,4]
 print is_Sorted(any_list)

โปรดทราบว่าสิ่งนี้จะเพิ่มขึ้นRuntimeError: maximum recursion depth exceededสำหรับรายการที่มีความยาว ลองany_list = range(1000)ดู
timgeb

-1

แล้วอันนี้ละ ? เรียบง่ายและตรงไปตรงมา

def is_list_sorted(al):

    llength =len(al)


    for i in range (llength):
        if (al[i-1] > al[i]):
            print(al[i])
            print(al[i+1])
            print('Not sorted')
            return -1

    else :
        print('sorted')
        return  true

-3

สามารถใช้งานได้ใน Python 3 และสูงกว่าสำหรับจำนวนเต็มหรือสตริงอย่างแน่นอน:

def tail(t):
    return t[:]

letters = ['a', 'b', 'c', 'd', 'e']
rest = tail(letters)
rest.sort()
if letters == rest:
    print ('Given list is SORTED.')
else:
    print ('List NOT Sorted.')

================================================== ===================

อีกวิธีหนึ่งในการค้นหาว่ามีการเรียงลำดับรายการหรือไม่

trees1 = list ([1, 4, 5, 3, 2])
trees2 = list (trees1)
trees2.sort()
if trees1 == trees2:
    print ('trees1 is SORTED')
else:
    print ('Not sorted')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.