อะไรคือความแตกต่างระหว่าง `sort (list)` vs `list.sort ()`?


194

list.sort()เรียงลำดับรายการและแทนที่รายการเดิมในขณะที่sorted(list)ส่งคืนสำเนาที่เรียงลำดับของรายการโดยไม่เปลี่ยนรายการดั้งเดิม

  • เมื่อใดที่หนึ่งต้องการมากกว่าอื่น ๆ
  • อันไหนมีประสิทธิภาพมากกว่ากัน? เท่าไหร่
  • รายการสามารถถูกเปลี่ยนกลับไปเป็นสถานะที่ไม่เรียงลำดับหลังจากlist.sort()ถูกดำเนินการได้หรือไม่?

4
ระวังถ้าคุณ (โดยบังเอิญ) โทรหาsorted()อาร์กิวเมนต์ string แต่คิดว่าเป็นรายการคุณจะได้รับรายการผลลัพธ์ไม่ใช่สตริง : sorted("abcd", reverse=True)ให้['d', 'c', 'b', 'a']ไม่ใช่"dcba"
smci

คำตอบ:


317

sorted()ส่งคืนรายการที่เรียงลำดับใหม่โดยปล่อยให้รายการเดิมไม่ได้รับผลกระทบ list.sort()เรียงลำดับรายการในสถานที่กลายพันธุ์ดัชนีรายการและผลตอบแทนNone(เช่นการดำเนินการในสถานที่ทั้งหมด)

sorted()ทำงานบน iterable ใด ๆ ไม่ใช่แค่รายการ สตริง, tuples, พจนานุกรม (คุณจะได้รับกุญแจ), เครื่องกำเนิด, ฯลฯ , ส่งคืนรายการที่มีองค์ประกอบทั้งหมด, เรียงลำดับ

  • ใช้list.sort()เมื่อคุณต้องการเปลี่ยนแปลงรายการsorted()เมื่อคุณต้องการให้วัตถุที่เรียงลำดับใหม่กลับมา ใช้sorted()เมื่อคุณต้องการที่จะเรียงลำดับสิ่งที่เป็น iterable ไม่รายการเลย

  • สำหรับรายการlist.sort()เร็วกว่าsorted()เพราะไม่ต้องสร้างสำเนา สำหรับ iterable อื่น ๆ คุณไม่มีทางเลือก

  • ไม่คุณไม่สามารถเรียกคืนตำแหน่งเดิมได้ เมื่อคุณเรียกว่าlist.sort()คำสั่งเดิมหายไป


6
โดยทั่วไปแล้วเมื่อฟังก์ชั่น python คืนค่าNoneมันเป็นสัญญาณว่าการดำเนินการเสร็จสิ้นนั่นคือสาเหตุที่เมื่อคุณต้องการพิมพ์list.sort()มันจะคืนค่า None
user1767754

45

ข้อแตกต่างระหว่างsorted(list)vs list.sort()คืออะไร?

  • list.sort ปิดท้ายรายการและส่งคืน None
  • sorted ใช้ซ้ำได้และส่งคืนรายการใหม่เรียงลำดับ

sorted เทียบเท่ากับการใช้งาน Python นี้ แต่ฟังก์ชั่น CPython ในตัวควรรันได้เร็วขึ้นอย่างรวดเร็วตามที่เขียนไว้ใน C:

def sorted(iterable, key=None):
    new_list = list(iterable)    # make a new list
    new_list.sort(key=key)       # sort it
    return new_list              # return it

จะใช้เมื่อใด

  • ใช้list.sortเมื่อคุณไม่ต้องการรักษาลำดับการจัดเรียงดั้งเดิม (ดังนั้นคุณจะสามารถนำรายการกลับมาใช้ซ้ำได้ในหน่วยความจำ) และเมื่อคุณเป็นเจ้าของรายการ แต่เพียงผู้เดียว (หากมีการแบ่งปันรายการด้วยรหัสอื่นและคุณ การกลายพันธุ์คุณสามารถแนะนำบั๊กที่ใช้รายการนั้น)
  • ใช้sortedเมื่อคุณต้องการรักษาลำดับการจัดเรียงดั้งเดิมหรือเมื่อคุณต้องการสร้างรายการใหม่ที่มีเฉพาะรหัสท้องถิ่นของคุณ

สามารถดึงตำแหน่งดั้งเดิมของรายการหลังจาก list.sort () ได้หรือไม่?

ไม่ - ถ้าคุณทำสำเนาด้วยตัวเองข้อมูลนั้นจะหายไปเนื่องจากการเรียงลำดับเสร็จสิ้นแล้ว

"และอันไหนเร็วกว่ากันและเร็วเท่าไหร่"

เพื่อแสดงให้เห็นถึงการลงโทษในการสร้างรายการใหม่ให้ใช้โมดูล timeit นี่คือการตั้งค่าของเรา:

import timeit
setup = """
import random
lists = [list(range(10000)) for _ in range(1000)]  # list of lists
for l in lists:
    random.shuffle(l) # shuffle each list
shuffled_iter = iter(lists) # wrap as iterator so next() yields one at a time
"""

และนี่คือผลลัพธ์ของเราสำหรับรายการของการจัดเรียงแบบสุ่ม 10,000 จำนวนเต็มตามที่เราเห็นที่นี่เราพิสูจน์หักล้างตำนานค่าใช้จ่ายในการสร้างรายการแบบเก่า :

Python 2.7

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[3.75168503401801, 3.7473005310166627, 3.753129180986434]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[3.702025591977872, 3.709248117986135, 3.71071034099441]

Python 3

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[2.797430992126465, 2.796825885772705, 2.7744789123535156]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[2.675589084625244, 2.8019039630889893, 2.849375009536743]

หลังจากข้อเสนอแนะบางอย่างฉันตัดสินใจว่าการทดสอบอื่นจะเป็นที่น่าพอใจด้วยคุณสมบัติที่แตกต่าง ที่นี่ฉันให้รายการเรียงลำดับแบบสุ่มที่มีความยาว 100,000 รายการสำหรับการวนซ้ำแต่ละครั้ง 1,000 ครั้ง

import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""

ฉันตีความความแตกต่างของการเรียงลำดับที่ใหญ่กว่านี้ซึ่งมาจากการคัดลอกที่กล่าวถึงโดย Martijn แต่มันไม่ได้ครองจุดที่ระบุไว้ในคำตอบที่ได้รับความนิยมมากกว่าเก่าที่นี่เวลาเพิ่มขึ้นเพียง 10%

>>> timeit.repeat("lst[:].sort()", setup=setup, number = 10000)
[572.919036605, 573.1384446719999, 568.5923951]
>>> timeit.repeat("sorted(lst[:])", setup=setup, number = 10000)
[647.0584738299999, 653.4040515829997, 657.9457361929999]

ฉันยังวิ่งไปด้านบนในประเภทที่เล็กกว่ามากและเห็นว่าsortedรุ่นสำเนาใหม่ยังคงใช้เวลาทำงานนานขึ้นประมาณ 2% ในความยาว 1,000 เท่า

Poke ใช้รหัสของเขาเองเช่นกันนี่คือรหัส:

setup = '''
import random
random.seed(12122353453462456)
lst = list(range({length}))
random.shuffle(lst)
lists = [lst[:] for _ in range({repeats})]
it = iter(lists)
'''
t1 = 'l = next(it); l.sort()'
t2 = 'l = next(it); sorted(l)'
length = 10 ** 7
repeats = 10 ** 2
print(length, repeats)
for t in t1, t2:
    print(t)
    print(timeit(t, setup=setup.format(length=length, repeats=repeats), number=repeats))

เขาค้นหาความยาว 1000000 เรียง (วิ่ง 100 ครั้ง) ผลลัพธ์ที่คล้ายกัน แต่เพิ่มขึ้นเพียง 5% ในเวลานี่คือผลลัพธ์:

10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655

สรุป:

รายการขนาดใหญ่ที่เรียงลำดับด้วยsortedการทำสำเนาอาจมีอิทธิพลเหนือความแตกต่าง แต่การเรียงลำดับจะควบคุมการดำเนินการและการจัดระเบียบรหัสของคุณเกี่ยวกับความแตกต่างเหล่านี้จะเป็นการปรับให้เหมาะสมก่อนกำหนด ฉันจะใช้sortedเมื่อฉันต้องการรายการที่เรียงลำดับใหม่ของข้อมูลและฉันจะใช้list.sortเมื่อฉันต้องการเรียงลำดับรายการในสถานที่และให้ที่กำหนดการใช้งานของฉัน


4
การตั้งค่าเครื่องกำเนิดไฟฟ้านั้นดี แต่ฉันจะไม่สรุปว่าคุณจับตำนานไปเร็วเกินไป ความเป็นจริงยังคงอยู่ที่sorted()ต้องจัดสรรวัตถุรายการใหม่และคัดลอกการอ้างอิง; ส่วนที่เหลือของเส้นทางรหัสจะเหมือนกัน ดูว่าคุณสามารถใช้การทดสอบเดียวกันกับรายการขนาดใหญ่ เปรียบเทียบด้วยการสร้างสำเนาของรายการและดูว่าคุณสามารถทำซ้ำความแตกต่างที่คุณพบ ฯลฯ
Martijn Pieters

11

ความแตกต่างที่สำคัญคือการsorted(some_list)ส่งคืนใหม่list :

a = [3, 2, 1]
print sorted(a) # new list
print a         # is not modified

และsome_list.sort(), เรียงลำดับรายการในสถานที่ :

a = [3, 2, 1]
print a.sort() # in place
print a         # it's modified

หมายเหตุว่าตั้งแต่a.sort()ไม่กลับอะไรจะพิมพ์print a.sort()None


สามารถดึงตำแหน่งดั้งเดิมของรายการหลังจาก list.sort () ได้หรือไม่?

ไม่เพราะจะแก้ไขรายการเดิม


1
print a.sort()จะไม่พิมพ์อะไรเลย
Burhan Khalid

1
มันจะพิมพ์Noneฉันจะชี้แจงว่า
Christian

1

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

คุณต้องเก็บค่าของเรียง (รายการ) ในตัวแปรอย่างชัดเจน

สำหรับการประมวลผลข้อมูลสั้น ๆ ความเร็วจะไม่มีความแตกต่าง แต่สำหรับรายการยาว คุณควรใช้. sort () โดยตรงเพื่อการทำงานที่รวดเร็ว; แต่คุณจะต้องเผชิญกับการกระทำที่กลับไม่ได้อีกครั้ง


"ฟังก์ชั่น. sort () เก็บค่าของรายการใหม่โดยตรงในตัวแปรลิสต์" หือ? รายการใหม่คืออะไร? ไม่มีรายการใหม่ list.sort()วิธีการเรียงลำดับวัตถุรายการในสถานที่
PM 2Ring

นอกจากนี้สิ่งนี้ควรจะหมายถึงอะไร "บางครั้ง. sort () วิธีการทำหน้าที่เป็นฟังก์ชั่นหรือบอกว่ามันใช้เวลาขัดแย้งในนั้น"
PM 2Ring

สิ่งที่ฉันหมายถึงโดยรายการใหม่คือรายการที่แก้ไขและ. sort () เพียงแค่เก็บรายการที่แก้ไขไว้ในตัวแปรเดียวกันนั้น
Vicrobot

ใช่.sort()วิธีการบางอย่างใช้อาร์กิวเมนต์และทำหน้าที่เป็นอย่างแน่นอน นอกจากนี้เราเรียกมันว่าวิธีการเพราะมันเป็นคุณสมบัติของรายการประเภทข้อมูล
Vicrobot

หากมีข้อผิดพลาดบางอย่างในแนวคิดของฉันแล้วบอกฉันฉันจะค้นหามันและจะปรับปรุงแนวคิดของฉันและคำตอบของฉันด้วย ขอบคุณ
Vicrobot

1

นี่คือตัวอย่างง่ายๆที่จะเห็นความแตกต่างในการกระทำ:

ดูรายการตัวเลขที่นี่:

nums = [1, 9, -3, 4, 8, 5, 7, 14]

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

มาดูกัน.

sorted(nums)

ผลตอบแทน

[-3, 1, 4, 5, 7, 8, 9, 14]

มองไปที่numsอีกครั้ง

nums

เราเห็นรายการเดิม (ไม่เปลี่ยนแปลงและไม่เรียงลำดับ) sortedไม่ได้เปลี่ยนรายการดั้งเดิม

[1, 2, -3, 4, 8, 5, 7, 14]

ใช้numsรายการเดียวกันและใช้sortฟังก์ชั่นนั้นจะเปลี่ยนรายการจริง

มาดูกัน.

เริ่มต้นด้วยnumsรายการของเราเพื่อให้แน่ใจว่าเนื้อหายังคงเหมือนเดิม

nums

[-3, 1, 4, 5, 7, 8, 9, 14]

nums.sort()

ตอนนี้รายการ nums เดิมจะเปลี่ยนไปและดู nums ที่เราเห็นว่ารายการเดิมมีการเปลี่ยนแปลงและเรียงลำดับแล้ว

nums
[-3, 1, 2, 4, 5, 7, 8, 14]

ขอบคุณที่แสดงต้นฉบับและสำเนาในเชิงลึกมากขึ้น
เบรนแดน

0

หมายเหตุ: ความแตกต่างที่ง่ายที่สุดระหว่าง sort () และ sort () คือ: sort () จะไม่ส่งคืนค่าใด ๆ ในขณะที่ sort () จะส่งคืนรายการที่สามารถทำซ้ำได้

sort () ไม่ส่งคืนค่าใด ๆ

วิธีการเรียง () เพียงแค่เรียงลำดับองค์ประกอบของรายการที่กำหนดในลำดับที่เฉพาะเจาะจง - น้อยไปหามากหรือจากมากไปน้อยโดยไม่ต้องคืนค่าใด ๆ

ไวยากรณ์ของการจัดเรียง () วิธีการคือ:

list.sort(key=..., reverse=...)

นอกจากนี้คุณยังสามารถใช้ฟังก์ชันที่จัดเรียงไว้ใน Python () เพื่อจุดประสงค์เดียวกัน ฟังก์ชันที่เรียงลำดับส่งคืนรายการที่เรียงลำดับ

 list=sorted(list, key=..., reverse=...)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.