การจัดเรียง Python

วิธีที่ง่ายที่สุดในการจัดเรียงคือการใช้ฟังก์ชัน Sort(list) ซึ่งจะสร้างรายการและแสดงผลรายการใหม่พร้อมองค์ประกอบเหล่านั้นตามลำดับ รายการต้นฉบับจะไม่มีการเปลี่ยนแปลง

  a = [5, 1, 4, 3]
  print(sorted(a))  ## [1, 3, 4, 5]
  print(a)  ## [5, 1, 4, 3]

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

สามารถปรับแต่งฟังก์ชัน Sort() โดยใช้อาร์กิวเมนต์ที่ไม่บังคับ อาร์กิวเมนต์ที่เรียงลำดับ (ไม่บังคับ) แบบย้อนกลับ=จริง เช่น จัดเรียง(รายการ, ย้อนกลับ=จริง) จะทำให้ระบบจัดเรียงย้อนหลัง

  strs = ['aa', 'BB', 'zz', 'CC']
  print(sorted(strs))  ## ['BB', 'CC', 'aa', 'zz'] (case sensitive)
  print(sorted(strs, reverse=True))   ## ['zz', 'aa', 'CC', 'BB']

การจัดเรียงที่กำหนดเองด้วยคีย์=

สำหรับการจัดเรียงที่กำหนดเองที่ซับซ้อนยิ่งขึ้น Sort() จะใช้ตัวเลือก "key=" ระบุฟังก์ชัน "key" ซึ่งจะเปลี่ยนรูปแบบแต่ละองค์ประกอบก่อนการเปรียบเทียบ ฟังก์ชันคีย์ใช้ 1 ค่าและแสดงผล 1 ค่า และระบบจะใช้ค่า "พร็อกซี" ที่แสดงผลในการเปรียบเทียบภายในการจัดเรียง

ตัวอย่างเช่น การระบุรายการสตริง การระบุ key=len (ฟังก์ชัน len() ในตัว) จะจัดเรียงสตริงตามความยาวจากสั้นที่สุดไปยาวที่สุด การจัดเรียงจะเรียก len() สำหรับแต่ละสตริงเพื่อรับรายการค่าความยาวพร็อกซี จากนั้นจัดเรียงตามค่าพร็อกซีเหล่านั้น

  strs = ['ccc', 'aaaa', 'd', 'bb']
  print(sorted(strs, key=len))  ## ['d', 'bb', 'ccc', 'aaaa']

จัดเรียงการโทรด้วย key=len

อีกตัวอย่างหนึ่งคือ การระบุ "str.lower" เป็นฟังก์ชันคีย์เป็นการบังคับให้การจัดเรียงไม่พิจารณาตัวพิมพ์ใหญ่และตัวพิมพ์เล็กที่เหมือนกัน ดังนี้

  ## "key" argument specifying str.lower function to use for sorting
  print(sorted(strs, key=str.lower))  ## ['aa', 'BB', 'CC', 'zz']

นอกจากนี้คุณยังส่งผ่าน MyFn ของคุณเองเป็นฟังก์ชันหลักได้ด้วย เช่น

  ## Say we have a list of strings we want to sort by the last letter of the string.
  strs = ['xc', 'zb', 'yd' ,'wa']

  ## Write a little function that takes a string, and returns its last letter.
  ## This will be the key function (takes in 1 value, returns 1 value).
  def MyFn(s):
    return s[-1]

  ## Now pass key=MyFn to sorted() to sort by the last letter:
  print(sorted(strs, key=MyFn))  ## ['wa', 'zb', 'xc', 'yd']

สำหรับการจัดเรียงที่ซับซ้อนขึ้น เช่น การจัดเรียงตามนามสกุลแล้วตามด้วยชื่อ คุณสามารถใช้ฟังก์ชัน itemgetter หรือ Attrgetter เช่น

  from operator import itemgetter

  # (first name, last name, score) tuples
  grade = [('Freddy', 'Frank', 3), ('Anil', 'Frank', 100), ('Anil', 'Wang', 24)]
  sorted(grade, key=itemgetter(1,0))
  # [('Anil', 'Frank', 100), ('Freddy', 'Frank', 3), ('Anil', 'Wang', 24)]

  sorted(grade, key=itemgetter(0,-1))
  #[('Anil', 'Wang', 24), ('Anil', 'Frank', 100), ('Freddy', 'Frank', 3)]

วิธีการ Sort()

วิธีการ Sort() ในรายการจะเป็นทางเลือกในการใช้การจัดเรียง() ในรายการจะจัดเรียงตามลำดับจากน้อยไปมาก เช่น list.sort() เมธอด Sort() จะเปลี่ยนรายการพื้นฐานและแสดงผล None ดังนั้นใช้รูปแบบนี้:

  alist.sort()            ## correct
  alist = blist.sort()    ## Incorrect. sort() returns None

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

กระโปรงบัลเลต์

Tuple คือการจัดกลุ่มขนาดคงที่ขององค์ประกอบ เช่น พิกัด (x, y) Tuple เป็นเหมือนกับรายการ เพียงแต่เปลี่ยนแปลงไม่ได้และไม่เปลี่ยนขนาด (Tuple นั้นจะเปลี่ยนแปลงไม่ได้อย่างเคร่งครัดเนื่องจากหนึ่งในองค์ประกอบที่มีอยู่อาจเปลี่ยนแปลงได้) Tuple มีบทบาท "struct" ใน Python ซึ่งเป็นวิธีที่สะดวกในการส่งต่อกลุ่มค่าที่มีขนาดคงที่เพียงเล็กน้อย ฟังก์ชันที่ต้องส่งคืนค่าหลายค่าสามารถแสดงผล Tuple ของค่าได้ ตัวอย่างเช่น ถ้าต้องการมีรายการของพิกัด 3 มิติ การแสดงงูหลามตามธรรมชาติจะเป็นรายการ tuple ที่แต่ละ Tuple มีขนาด 3 โดยมีกลุ่ม 1 (x, y, z)

ในการสร้าง Tuple เพียงแสดงรายการค่าภายในวงเล็บโดยคั่นด้วยเครื่องหมายจุลภาค ตูเปิล "ว่าง" เป็นเพียงวงเล็บคู่ที่ว่างเปล่า การเข้าถึงองค์ประกอบใน Tuple เหมือนกับรายการ len(), [ ], for, in ฯลฯ จะเหมือนกันทั้งหมด

  tuple = (1, 2, 'hi')
  print(len(tuple))  ## 3
  print(tuple[2])    ## hi
  tuple[2] = 'bye'  ## NO, tuples cannot be changed
  tuple = (1, 2, 'bye')  ## this works

หากต้องการสร้าง Tuple ขนาด 1 องค์ประกอบเดี่ยวต้องตามด้วยเครื่องหมายจุลภาค

  tuple = ('hi',)   ## size-1 tuple

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

การกำหนด Tuple ให้กับ Tuple ที่มีขนาดเท่ากันของชื่อตัวแปรจะเป็นการกำหนดค่าที่สอดคล้องกันทั้งหมด หาก Tuple มีขนาดต่างกัน ระบบจะแสดงข้อผิดพลาด ฟีเจอร์นี้ใช้ได้กับรายการเช่นกัน

  (x, y, z) = (42, 13, "hike")
  print(z)  ## hike
  (err_string, err_code) = Foo()  ## Foo() returns a length-2 tuple

แสดงรายการความเข้าใจ (ไม่บังคับ)

ความเข้าใจแบบรายการเป็นฟีเจอร์ขั้นสูงซึ่งเป็นเรื่องที่ดีในบางกรณี แต่ไม่จำเป็นสำหรับแบบฝึกหัด และคุณไม่จำเป็นต้องเรียนรู้ตั้งแต่แรก (เช่น คุณสามารถข้ามส่วนนี้ได้) การทำความเข้าใจรายการเป็นวิธีแบบกะทัดรัดในการเขียนนิพจน์ที่ขยายไปยังรายการทั้งหมด สมมติว่าเรามีรายการเลขที่ [1, 2, 3, 4] ต่อไปนี้เป็นความเข้าใจของรายการสำหรับคำนวณรายการกำลังสอง [1, 4, 9, 16]

  nums = [1, 2, 3, 4]

  squares = [ n * n for n in nums ]   ## [1, 4, 9, 16]

ไวยากรณ์คือ [ expr for var in list ] -- for var in list มีลักษณะเหมือน for-loop ปกติ แต่ไม่มีเครื่องหมายโคลอน (:) ระบบจะประเมิน expr ทางด้านซ้ายเพียงครั้งเดียวสำหรับแต่ละองค์ประกอบเพื่อให้ค่าสำหรับรายการใหม่ ต่อไปนี้เป็นตัวอย่างที่มีสตริง โดยที่แต่ละสตริงจะเปลี่ยนไปเป็นตัวพิมพ์ใหญ่โดยมี "!!!" ต่อท้าย

  strs = ['hello', 'and', 'goodbye']

  shouting = [ s.upper() + '!!!' for s in strs ]
  ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']

คุณสามารถเพิ่มการทดสอบ if ที่ด้านขวาของ for-loop เพื่อจำกัดผลลัพธ์ให้แคบลงได้ มีการประเมินการทดสอบ if สำหรับแต่ละองค์ประกอบ ซึ่งรวมถึงเฉพาะองค์ประกอบที่การทดสอบเป็นจริงเท่านั้น

  ## Select values <= 2
  nums = [2, 8, 1, 6]
  small = [ n for n in nums if n <= 2 ]  ## [2, 1]

  ## Select fruits containing 'a', change to upper case
  fruits = ['apple', 'cherry', 'banana', 'lemon']
  afruits = [ s.upper() for s in fruits if 'a' in s ]
  ## ['APPLE', 'BANANA']

แบบฝึกหัด: list1.py

หากต้องการฝึกเนื้อหาในส่วนนี้ ให้ลองทำโจทย์ข้อต่อไปนี้ใน list1.py ซึ่งใช้การจัดเรียงและ Tuple (ในแบบฝึกหัดพื้นฐาน)