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

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

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

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

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

  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=" ที่ไม่บังคับ การระบุ "คีย์" ที่เปลี่ยนรูปแบบองค์ประกอบแต่ละรายการก่อนการเปรียบเทียบ ฟังก์ชันคีย์จะใช้ค่า 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()

นอกจากจะจัดเรียง() แล้ว วิธีจัดเรียง() ในรายการจะจัดเรียงรายการดังกล่าวตามลำดับจากน้อยไปมาก เช่น list.sort() เมธอด Sort() จะเปลี่ยนรายการที่สำคัญและแสดงค่า "ไม่มี" ดังนั้น ให้ใช้รูปแบบดังนี้

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

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

ตูเปิล

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

หากต้องการสร้าง Tuple เพียงแสดงค่าภายในวงเล็บและคั่นด้วยเครื่องหมายจุลภาค คอลัมน์ "ว่างเปล่า" 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 ให้กับชื่อตัวแปรที่มีขนาดเท่ากันจะกำหนดค่าที่เกี่ยวข้องทั้งหมด หากผ้าอ้อมมีขนาดไม่เท่ากัน ระบบจะแสดงข้อผิดพลาด ฟีเจอร์นี้ใช้ได้กับรายการด้วยเช่นกัน

  (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 ทางด้านซ้าย 1 ครั้งสำหรับแต่ละองค์ประกอบเพื่อให้ค่าสำหรับรายการใหม่ นี่คือตัวอย่างของสตริง ซึ่งแต่ละสตริงจะมีการเปลี่ยนแปลงเป็นอักษรตัวพิมพ์ใหญ่ด้วย "!!!" ต่อท้าย:

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

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

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

  ## 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 ที่ใช้การจัดเรียงและทวีคูณ (ในแบบฝึกหัดพื้นฐาน)