ฉันไม่เข้าใจไวยากรณ์หลังsorted()
อาร์กิวเมนต์:
key=lambda variable: variable[0]
มันไม่ได้lambda
ตามอำเภอใจเหรอ? ทำไมvariable
ที่ระบุไว้สองครั้งในสิ่งที่ดูเหมือนว่าdict
?
ฉันไม่เข้าใจไวยากรณ์หลังsorted()
อาร์กิวเมนต์:
key=lambda variable: variable[0]
มันไม่ได้lambda
ตามอำเภอใจเหรอ? ทำไมvariable
ที่ระบุไว้สองครั้งในสิ่งที่ดูเหมือนว่าdict
?
คำตอบ:
key
เป็นฟังก์ชั่นที่จะถูกเรียกให้แปลงรายการของคอลเลกชันก่อนที่จะถูกเปรียบเทียบ พารามิเตอร์ที่ส่งผ่านไปkey
จะต้องเป็นสิ่งที่เรียกได้
การใช้lambda
สร้างฟังก์ชั่นที่ไม่ระบุชื่อ (ซึ่งเรียกได้) ในกรณีsorted
ที่ callable ใช้เพียงหนึ่งพารามิเตอร์ Python lambda
นั้นค่อนข้างเรียบง่าย มันสามารถทำได้และส่งคืนสิ่งหนึ่งเท่านั้นจริงๆ
ไวยากรณ์ของlambda
คือคำที่lambda
ตามด้วยรายการชื่อพารามิเตอร์จากนั้นบล็อกหนึ่งรหัส รายการพารามิเตอร์และการบล็อกรหัสถูกกำหนดโดยโคลอน นี้จะคล้ายกับโครงสร้างอื่น ๆ ในหลามเช่นกันเช่นwhile
, for
, if
และอื่น ๆ พวกเขาเป็นงบทั้งหมดที่มักจะมีการบล็อกรหัส แลมบ์ดาเป็นอีกตัวอย่างหนึ่งของคำสั่งที่มีการบล็อกรหัส
เราสามารถเปรียบเทียบการใช้แลมบ์ดากับของ def เพื่อสร้างฟังก์ชั่น
adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2
แลมบ์ดาให้วิธีในการทำสิ่งนี้กับเราโดยไม่ต้องระบุชื่อ ซึ่งทำให้ยอดเยี่ยมสำหรับการใช้เป็นพารามิเตอร์ของฟังก์ชัน
variable
มีการใช้สองครั้งที่นี่เพราะทางด้านซ้ายของเครื่องหมายโคลอนจะเป็นชื่อของพารามิเตอร์และทางด้านขวามือจะใช้ในบล็อกโค้ดเพื่อคำนวณบางอย่าง
ฉันคิดว่าคำตอบทั้งหมดที่นี่ครอบคลุมหลักของสิ่งที่ฟังก์ชั่นแลมบ์ดาในบริบทของการเรียงลำดับ () ค่อนข้างดี แต่ฉันยังรู้สึกเหมือนคำอธิบายที่นำไปสู่ความเข้าใจที่เข้าใจง่ายขาดนี่คือสองเซ็นต์ของฉัน
เพื่อประโยชน์ของความสมบูรณ์ฉันจะแจ้งให้ทราบล่วงหน้า: sort () ส่งกลับรายการขององค์ประกอบที่เรียงและถ้าเราต้องการเรียงลำดับในลักษณะเฉพาะหรือถ้าเราต้องการเรียงลำดับรายการที่ซับซ้อนขององค์ประกอบ (เช่นรายการซ้อนหรือ รายการของ tuples) เราสามารถเรียกใช้อาร์กิวเมนต์ที่สำคัญ
สำหรับฉันความเข้าใจอย่างถ่องแท้เกี่ยวกับข้อโต้แย้งที่สำคัญว่าทำไมจึงต้องมี callable และการใช้แลมบ์ดาเป็นฟังก์ชั่น callable (ไม่ระบุชื่อ) เพื่อให้บรรลุสิ่งนี้มาในสองส่วน
ไวยากรณ์ของแลมบ์ดาเป็นดังนี้:
แลมบ์ดาinput_variable (s) : อร่อยหนึ่งซับ
เช่น
In [1]: f00 = lambda x: x/2
In [2]: f00(10)
Out[2]: 5.0
In [3]: (lambda x: x/2)(10)
Out[3]: 5.0
In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0
In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
key
โต้แย้งคือควรใช้ชุดคำสั่งที่จะชี้ฟังก์ชัน 'sort ()' ที่องค์ประกอบรายการเหล่านั้นซึ่งควรใช้ในการเรียงลำดับ เมื่อมันบอกkey=
ว่ามันหมายถึงอะไรจริงๆ: เมื่อฉันวนซ้ำองค์ประกอบหนึ่งรายการในแต่ละครั้ง (เช่นสำหรับ e ในรายการ) ฉันจะส่งองค์ประกอบปัจจุบันไปยังฟังก์ชันที่ฉันให้ไว้ในอาร์กิวเมนต์ที่สำคัญและใช้สิ่งนั้น เพื่อสร้างรายการที่แปลงแล้วซึ่งจะแจ้งให้ฉันทราบเกี่ยวกับลำดับของรายการที่เรียงลำดับสุดท้ายลองดูสิ:
mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)
ตัวอย่างฐาน:
sorted(mylist)
[2, 3, 3, 4, 6, 8, 23] # ตัวเลขทั้งหมดเรียงตามลำดับจากเล็กไปใหญ่
ตัวอย่างที่ 1:
mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)
[3, 3, 23, 6, 2, 4, 8] # ผลลัพธ์ที่เรียงลำดับนี้เหมาะสมกับคุณหรือไม่
โปรดสังเกตว่าฟังก์ชั่นแลมบ์ดาของฉันบอกว่าเรียงลำดับเพื่อตรวจสอบว่า (e) เป็นเลขคู่หรือคี่ก่อนที่จะเรียงลำดับ
แต่เดี๋ยวก่อน! คุณอาจสงสัย (หรือควรจะ) สองสิ่ง - ก่อนทำไมราคาของฉันมาก่อนเหตุการณ์ของฉัน (เนื่องจากค่าคีย์ของฉันดูเหมือนจะบอกฟังก์ชั่นการเรียงลำดับของฉันเพื่อจัดลำดับความสำคัญของเหตุการณ์โดยใช้ตัวดำเนินการ mod x%2==0
) ประการที่สองทำไมฉันถึงไม่เป็นระเบียบ? 2 มาก่อน 6 ใช่ไหม? โดยการวิเคราะห์ผลลัพธ์นี้เราจะได้เรียนรู้สิ่งที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับวิธีการเรียงลำดับ () คีย์ 'อาร์กิวเมนต์' โดยเฉพาะอย่างยิ่งเมื่อใช้ร่วมกับฟังก์ชันแลมบ์ดานิรนาม
ประการแรกคุณจะสังเกตเห็นว่าในขณะที่อัตราต่อรองมาก่อนที่ Evens, Evens ตัวเองไม่ได้เรียง ทำไมนี้ ให้อ่านเอกสาร :
ฟังก์ชั่นคีย์เริ่มต้นด้วย Python 2.4 ทั้ง list.sort () และเรียง () เพิ่มพารามิเตอร์คีย์เพื่อระบุฟังก์ชั่นที่จะเรียกใช้ในแต่ละรายการก่อนที่จะทำการเปรียบเทียบ
เราต้องอ่านนิดหน่อยระหว่างบรรทัดที่นี่ แต่สิ่งที่บอกเราคือฟังก์ชั่นการเรียงลำดับจะถูกเรียกเพียงครั้งเดียวและถ้าเราระบุอาร์กิวเมนต์หลักเราจะเรียงตามค่าที่ฟังก์ชันหลักชี้ไป
ตัวอย่างการใช้โมดูโล่ส่งคืนอะไร ค่าบูลีน: True == 1
, False == 0
. ดังนั้นการเรียงลำดับจะจัดการกับคีย์นี้อย่างไร โดยทั่วไปจะแปลงรายการดั้งเดิมเป็นลำดับ 1 และ 0
[3,6,3,2,4,8,23] กลายเป็น [0,1,0,1,1,1,1,0]
ตอนนี้เรากำลังเดินทางอยู่ที่ไหนซักแห่ง คุณจะได้อะไรเมื่อคุณเรียงลำดับรายการที่ถูกแปลง?
[0,0,0,1,1,1,1]
ตกลงดังนั้นตอนนี้เรารู้ว่าทำไมอัตราต่อรองมาก่อนเหตุการณ์ แต่คำถามต่อไปคือ: ทำไม 6 ถึงยังมาก่อน 2 ในรายการสุดท้ายของฉัน ง่ายมาก - เพราะการเรียงลำดับเกิดขึ้นเพียงครั้งเดียว! นั่นคือ 1s เหล่านั้นยังคงเป็นตัวแทนของค่ารายการดั้งเดิมซึ่งอยู่ในตำแหน่งดั้งเดิมที่สัมพันธ์กัน เนื่องจากการเรียงลำดับจะเกิดขึ้นเพียงครั้งเดียวและเราไม่เรียกฟังก์ชันเรียงลำดับใด ๆ เพื่อเรียงลำดับค่าดั้งเดิมจากต่ำไปสูงค่าเหล่านั้นยังคงอยู่ในลำดับเดิมที่สัมพันธ์กัน
คำถามสุดท้ายคือคำถามนี้ฉันจะคิดอย่างไรเกี่ยวกับแนวคิดว่าค่าบูลีนของฉันจะเปลี่ยนกลับไปเป็นค่าดั้งเดิมได้อย่างไรเมื่อฉันพิมพ์รายการที่เรียงลำดับสุดท้าย
Sorted () เป็นวิธีการในตัวที่ (สนุกจริง) ใช้อัลกอริทึมการจัดเรียงไฮบริดที่เรียกว่าTimsortที่รวมแง่มุมของการผสานการเรียงลำดับและการเรียงลำดับการแทรก เห็นได้ชัดว่าเมื่อคุณเรียกมันว่ามีกลไกที่เก็บค่าเหล่านี้ไว้ในหน่วยความจำและรวมเข้ากับตัวตนบูลีน (มาสก์) ซึ่งกำหนดโดย (... !) ฟังก์ชั่นแลมบ์ดา คำสั่งจะถูกกำหนดโดยตัวตนบูลีนที่คำนวณจากฟังก์ชันแลมบ์ดา แต่โปรดจำไว้ว่ารายการย่อยเหล่านี้ (ของรายการและศูนย์) จะไม่เรียงลำดับตามค่าดั้งเดิม ดังนั้นรายการสุดท้ายในขณะที่จัดระเบียบโดย Odds และ Evens จะไม่เรียงลำดับตามรายการย่อย (Evens ในกรณีนี้ไม่เป็นระเบียบ) ความจริงที่ว่าอัตราต่อรองที่ถูกสั่งซื้อเป็นเพราะพวกเขาอยู่ในลำดับโดยบังเอิญในรายการเดิม สิ่งที่นำมาจากทั้งหมดนี้คือเมื่อแลมบ์ดาทำการเปลี่ยนแปลงนั้นลำดับเดิมของรายการย่อยจะถูกเก็บไว้
แล้วทั้งหมดนี้เกี่ยวข้องกับคำถามเดิมอย่างไรและที่สำคัญกว่านั้นคือสัญชาตญาณของเราว่าเราควรใช้การเรียงลำดับ () ด้วยอาร์กิวเมนต์หลักและแลมบ์ดาอย่างไร
ฟังก์ชั่นแลมบ์ดานั้นคิดว่าเป็นตัวชี้ที่ชี้ไปยังค่าที่เราต้องการเรียงลำดับไม่ว่าจะเป็นตัวชี้การแมปค่ากับบูลีนที่แปลงโดยฟังก์ชันแลมบ์ดาหรือถ้าองค์ประกอบเฉพาะในรายการซ้อน dict ฯลฯ ถูกกำหนดอีกครั้งโดยฟังก์ชั่นแลมบ์ดา
ลองและทำนายว่าจะเกิดอะไรขึ้นเมื่อฉันเรียกใช้รหัสต่อไปนี้
mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])
sorted
เห็นได้ชัดว่าสายของฉันพูดว่า "โปรดเรียงลำดับรายการนี้" อาร์กิวเมนต์ key ทำให้มีความเฉพาะเจาะจงมากขึ้นโดยการพูดสำหรับแต่ละองค์ประกอบ (x) ใน mylist ให้ส่งคืนดัชนี1ขององค์ประกอบนั้นแล้วเรียงลำดับองค์ประกอบทั้งหมดของรายการเดิม 'mylist' ตามลำดับการเรียงลำดับของรายการที่คำนวณโดย ฟังก์ชั่นแลมบ์ดา เนื่องจากเรามีรายการสิ่งอันดับเราสามารถส่งคืนองค์ประกอบที่จัดทำดัชนีจากสิ่งอันดับ ดังนั้นเราจึงได้รับ:
[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]
เรียกใช้รหัสนั้นและคุณจะพบว่านี่คือคำสั่ง ลองสร้างดัชนีรายการจำนวนเต็มและคุณจะพบว่าตัวแบ่งรหัส
นี่เป็นคำอธิบายที่ยืดยาว แต่ฉันหวังว่านี่จะช่วย 'จัดเรียง' สัญชาตญาณของคุณเกี่ยวกับการใช้ฟังก์ชั่นแลมบ์ดาเป็นอาร์กิวเมนต์หลักในการเรียงลำดับ () และอื่น ๆ
key
ฟังก์ชั่น หากคุณพยายามที่จะเข้าใจsorted
ฟังก์ชั่นlambda
ไวยากรณ์เหล่านั้นจะเข้าสู่ความเข้าใจ
3
เพราะมันถูกส่งผ่านไปยังฟังก์ชั่น parens อยู่รอบแลมบ์ดาเพื่อไม่ให้มีการแยกวิเคราะห์นิพจน์lambda x: x+2(3)
ซึ่งไม่ถูกต้องเนื่องจาก2
ไม่ใช่ฟังก์ชัน
variable
ซ้ายของ:
เป็นชื่อพารามิเตอร์ การใช้งานของvariable
ด้านขวาคือการใช้พารามิเตอร์
หมายถึงเกือบเหมือนกับ:
def some_method(variable):
return variable[0]
อีกหนึ่งตัวอย่างของการใช้งาน sort ()ฟังก์ชั่นที่มี key = lambda สมมติว่าคุณมีรายการสิ่งอันดับ ใน tuple แต่ละอันคุณมียี่ห้อรุ่นและน้ำหนักของรถและคุณต้องการเรียงลำดับรายการของ tuples ตามยี่ห้อรุ่นหรือน้ำหนัก คุณสามารถทำได้ด้วยแลมบ์ดา
cars = [('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000), ('bmw', 'x5', 1700)]
print(sorted(cars, key=lambda car: car[0]))
print(sorted(cars, key=lambda car: car[1]))
print(sorted(cars, key=lambda car: car[2]))
ผล:
[('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000)]
[('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100)]
[('citroen', 'xsara', 1100), ('bmw', 'x5', 1700), ('lincoln', 'navigator', 2000)]
lambda
เป็นฟังก์ชั่นนิรนามไม่ใช่ฟังก์ชั่นโดยพลการ พารามิเตอร์ที่ได้รับการยอมรับจะเป็นตัวแปรที่คุณใช้งานและคอลัมน์ที่คุณกำลังเรียงลำดับ
เนื่องจากการใช้แลมบ์ดาถูกถามในบริบทของsorted()
ลองดูที่นี่ด้วยhttps://wiki.python.org/moin/HowTo/Sorting/#Key_Functions
เพียงเพื่อใช้ถ้อยคำใหม่กุญแจ (เป็นทางเลือกฟังก์ชั่นเพื่อดำเนินการเพื่อตัดสินใจสั่งซื้อค่าเริ่มต้นคือไม่มี) ในฟังก์ชั่นที่เรียงลำดับคาดว่าจะมีฟังก์ชั่นและคุณใช้แลมบ์ดา
ในการกำหนดแลมบ์ดาคุณระบุคุณสมบัติของวัตถุที่คุณต้องการเรียงลำดับและฟังก์ชั่นการเรียงลำดับในตัวของงูใหญ่จะดูแลโดยอัตโนมัติ
หากคุณต้องการเรียงลำดับตามคุณสมบัติหลายรายการให้กำหนด key = lambda x: (property1, property2)
ในการระบุคำสั่งซื้อโดยส่งผ่าน reverse = true เป็นอาร์กิวเมนต์ที่สาม (เป็นทางเลือกบูลีน False จะเรียงลำดับจากน้อยไปมาก True จะเรียงจากมากไปน้อยค่าเริ่มต้นคือเท็จ) ของฟังก์ชันที่เรียงลำดับ
คำตอบที่ง่ายและไม่เสียเวลากับตัวอย่างที่เกี่ยวข้องกับคำถามที่ถาม ทำตามตัวอย่างนี้:
user = [{"name": "Dough", "age": 55},
{"name": "Ben", "age": 44},
{"name": "Citrus", "age": 33},
{"name": "Abdullah", "age":22},
]
print(sorted(user, key=lambda el: el["name"]))
print(sorted(user, key= lambda y: y["age"]))
ดูชื่อในรายการพวกเขาเริ่มต้นด้วย D, B, C และ A และถ้าคุณสังเกตเห็นอายุพวกเขาคือ 55, 44, 33 และ 22 รหัสการพิมพ์ครั้งแรก
print(sorted(user, key=lambda el: el["name"]))
ผลลัพธ์ไปที่:
[{'name': 'Abdullah', 'age': 22},
{'name': 'Ben', 'age': 44},
{'name': 'Citrus', 'age': 33},
{'name': 'Dough', 'age': 55}]
เรียงลำดับชื่อเพราะโดย key = lambda el: el ["name"] เรากำลังเรียงลำดับชื่อและชื่อส่งกลับตามลำดับตัวอักษร
รหัสการพิมพ์ที่สอง
print(sorted(user, key= lambda y: y["age"]))
ผลลัพธ์:
[{'name': 'Abdullah', 'age': 22},
{'name': 'Citrus', 'age': 33},
{'name': 'Ben', 'age': 44},
{'name': 'Dough', 'age': 55}]
เรียงตามอายุและด้วยเหตุนี้รายการจึงส่งกลับตามลำดับอายุ
ลองใช้รหัสนี้เพื่อความเข้าใจที่ดีขึ้น
def
ถ้าคุณพบว่าตัวเองทำเช่นนี้คุณอาจจะเพียงแค่ใช้