Tôi không hiểu cú pháp đằng sau sorted()
đối số:
key=lambda variable: variable[0]
Không lambda
độc đoán sao? Tại sao được variable
nêu hai lần trong những gì trông giống như một dict
?
Tôi không hiểu cú pháp đằng sau sorted()
đối số:
key=lambda variable: variable[0]
Không lambda
độc đoán sao? Tại sao được variable
nêu hai lần trong những gì trông giống như một dict
?
Câu trả lời:
key
là một chức năng sẽ được gọi để chuyển đổi các mục của bộ sưu tập trước khi chúng được so sánh. Tham số được truyền chokey
phải là một cái gì đó có thể gọi được.
Việc sử dụng lambda
tạo một hàm ẩn danh (có thể gọi được). Trong trường hợp có sorted
thể gọi được chỉ mất một tham số. Python lambda
là khá đơn giản. Nó chỉ có thể làm và trả lại một điều thực sự.
Cú pháp của lambda
là từ lambda
theo sau là danh sách các tên tham số sau đó là một khối mã. Danh sách tham số và khối mã được mô tả bằng dấu hai chấm. Điều này tương tự cấu trúc khác trong python cũng như while
, for
,if
và vân vân. Chúng là tất cả các câu lệnh thường có một khối mã. Lambda chỉ là một ví dụ khác của một câu lệnh với một khối mã.
Chúng ta có thể so sánh việc sử dụng lambda với def để tạo hàm.
adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2
lambda chỉ cho chúng ta một cách để làm điều này mà không cần gán tên. Điều này làm cho nó tuyệt vời để sử dụng như là một tham số cho một chức năng.
variable
được sử dụng hai lần ở đây vì ở bên trái dấu hai chấm, đó là tên của một tham số và ở phía bên phải, nó đang được sử dụng trong khối mã để tính toán một cái gì đó.
Tôi nghĩ rằng tất cả các câu trả lời ở đây bao gồm cốt lõi của chức năng lambda trong bối cảnh được sắp xếp () khá độc đáo, tuy nhiên tôi vẫn cảm thấy như một mô tả dẫn đến sự hiểu biết trực quan còn thiếu, vì vậy đây là hai xu của tôi.
Để hoàn thiện, tôi sẽ nêu rõ mặt trước: sort () trả về một danh sách các phần tử được sắp xếp và nếu chúng ta muốn sắp xếp theo một cách cụ thể hoặc nếu chúng ta muốn sắp xếp một danh sách các phần tử phức tạp (ví dụ: danh sách lồng nhau hoặc một danh sách các bộ dữ liệu) chúng ta có thể gọi đối số chính.
Đối với tôi, sự hiểu biết trực quan về đối số chính, tại sao nó phải có thể gọi được và việc sử dụng lambda làm hàm có thể gọi được (ẩn danh) để thực hiện điều này có hai phần.
Cú pháp Lambda như sau:
lambda input_variable (s) : ngon một lót
ví dụ
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
đối số là nó sẽ đưa vào một tập hợp các hướng dẫn về cơ bản sẽ trỏ hàm 'sort ()' vào các phần tử danh sách nên được sử dụng để sắp xếp theo. Khi nó nói key=
, điều thực sự có nghĩa là: Khi tôi lặp qua danh sách một phần tử tại một thời điểm (nghĩa là cho e trong danh sách), tôi sẽ chuyển phần tử hiện tại cho hàm tôi cung cấp trong đối số khóa và sử dụng hàm đó để tạo một danh sách được chuyển đổi sẽ thông báo cho tôi về thứ tự của danh sách được sắp xếp cuối cùng.Kiểm tra xem nó:
mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)
Ví dụ cơ bản:
sorted(mylist)
[2, 3, 3, 4, 6, 8, 23] # tất cả các số theo thứ tự từ nhỏ đến lớn.
Ví dụ 1:
mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)
[3, 3, 23, 6, 2, 4, 8] # Kết quả được sắp xếp này có hợp lý với bạn không?
Lưu ý rằng hàm lambda của tôi được sắp xếp để kiểm tra xem (e) là chẵn hay lẻ trước khi sắp xếp.
NHƯNG CHỜ ĐỢI! Bạn có thể (hoặc có lẽ nên) tự hỏi hai điều - đầu tiên, tại sao tỷ lệ cược của tôi lại xuất hiện trước evens của tôi (vì giá trị khóa của tôi dường như đang nói với chức năng được sắp xếp của tôi để ưu tiên evens bằng cách sử dụng toán tử mod trongx%2==0
). Thứ hai, tại sao evens của tôi ra khỏi trật tự? 2 đến trước 6 phải không? Bằng cách phân tích kết quả này, chúng ta sẽ tìm hiểu một cái gì đó sâu hơn về cách đối số được sắp xếp () 'key' hoạt động, đặc biệt là kết hợp với hàm lambda ẩn danh.
Đầu tiên, bạn sẽ nhận thấy rằng trong khi tỷ lệ cược đến trước khi phát sinh, bản thân các evens không được sắp xếp. Tại sao lại thế này ?? Hãy đọc tài liệu :
Các hàm chính Bắt đầu với Python 2.4, cả list.sort () và sort () đã thêm một tham số khóa để chỉ định một hàm được gọi trên mỗi phần tử danh sách trước khi so sánh.
Chúng ta phải đọc một chút giữa các dòng ở đây, nhưng điều này cho chúng ta biết là hàm sắp xếp chỉ được gọi một lần và nếu chúng ta chỉ định đối số khóa, thì chúng ta sắp xếp theo giá trị mà hàm khóa chỉ cho chúng ta.
Vì vậy, ví dụ sử dụng trả lại modulo là gì? Một giá trị boolean: True == 1
, False == 0
. Vậy làm thế nào để sắp xếp đối phó với chìa khóa này? Về cơ bản, nó biến đổi danh sách ban đầu thành một chuỗi 1 và 0.
[3,6,3,2,4,8,23] trở thành [0,1,0,1,1,1,0]
Bây giờ chúng tôi đang nhận được ở đâu đó. Bạn nhận được gì khi sắp xếp danh sách đã chuyển đổi?
[0,0,0,1,1,1,1]
Được rồi, vì vậy bây giờ chúng tôi biết tại sao tỷ lệ cược đến trước khi phát sinh. Nhưng câu hỏi tiếp theo là: Tại sao số 6 vẫn đến trước số 2 trong danh sách cuối cùng của tôi? Chà điều đó thật dễ dàng - bởi vì việc sắp xếp chỉ xảy ra một lần! tức là những số 1 đó vẫn đại diện cho các giá trị danh sách ban đầu, nằm ở vị trí ban đầu của chúng so với nhau. Vì việc sắp xếp chỉ xảy ra một lần và chúng tôi không gọi bất kỳ loại hàm sắp xếp nào để sắp xếp các giá trị chẵn gốc từ thấp đến cao, các giá trị đó vẫn theo thứ tự ban đầu so với nhau.
Câu hỏi cuối cùng là đây: Làm thế nào để tôi suy nghĩ một cách khái niệm về cách thứ tự các giá trị boolean của tôi được chuyển đổi trở lại các giá trị ban đầu khi tôi in ra danh sách được sắp xếp cuối cùng?
Sắp xếp () là một phương thức tích hợp sẵn (thực tế thú vị) sử dụng thuật toán sắp xếp lai được gọi là Timsortkết hợp các khía cạnh của sắp xếp hợp nhất và sắp xếp chèn. Đối với tôi có vẻ rõ ràng rằng khi bạn gọi nó, có một thợ máy giữ các giá trị này trong bộ nhớ và gói chúng với danh tính boolean (mặt nạ) được xác định bởi (...!) Hàm lambda. Thứ tự được xác định bởi danh tính boolean của chúng được tính từ hàm lambda, nhưng hãy nhớ rằng các danh sách con này (của một và số không) không được tự sắp xếp theo các giá trị ban đầu của chúng. Do đó, danh sách cuối cùng, trong khi được sắp xếp bởi Odds và Evens, không được sắp xếp theo danh sách phụ (các evens trong trường hợp này không theo thứ tự). Thực tế là tỷ lệ cược được đặt hàng là do chúng đã được sắp xếp theo thứ tự ngẫu nhiên trong danh sách ban đầu. Điểm nổi bật của tất cả những điều này là khi lambda thực hiện chuyển đổi đó, thứ tự ban đầu của danh sách con được giữ lại.
Vậy làm thế nào để tất cả những điều này liên quan trở lại câu hỏi ban đầu, và quan trọng hơn, trực giác của chúng ta về cách chúng ta nên thực hiện sắp xếp () với đối số chính và lambda của nó?
Hàm lambda đó có thể được coi là một con trỏ trỏ đến các giá trị mà chúng ta cần sắp xếp, cho dù con trỏ của nó ánh xạ một giá trị đến boolean của nó được biến đổi bởi hàm lambda hay nếu một phần tử cụ thể của nó trong danh sách lồng nhau, tuple, dict, vv, một lần nữa được xác định bởi chức năng lambda.
Hãy thử và dự đoán những gì sẽ xảy ra khi tôi chạy đoạn mã sau.
mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])
Cuộc sorted
gọi của tôi rõ ràng nói, "Hãy sắp xếp danh sách này". Đối số khóa làm cho cụ thể hơn một chút bằng cách nói, đối với mỗi phần tử (x) trong danh sách của tôi , trả về chỉ số 1 của phần tử đó, sau đó sắp xếp tất cả các phần tử của danh sách gốc 'mylist' theo thứ tự được sắp xếp của danh sách được tính theo hàm lambda. Vì chúng tôi có một danh sách các bộ dữ liệu, chúng tôi có thể trả về một phần tử được lập chỉ mục từ bộ dữ liệu đó. Vì vậy, chúng tôi nhận được:
[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]
Chạy mã đó và bạn sẽ thấy rằng đây là thứ tự. Hãy thử lập chỉ mục một danh sách các số nguyên và bạn sẽ thấy rằng mã bị hỏng.
Đây là một lời giải thích dài dòng, nhưng tôi hy vọng điều này sẽ giúp 'sắp xếp' trực giác của bạn về việc sử dụng các hàm lambda làm đối số chính trong sort () và hơn thế nữa.
key
chức năng này. Nếu bạn đang cố gắng hiểu sorted
chức năng, thì lambda
cú pháp sẽ đi vào cách hiểu.
lambda
là một từ khóa Python được sử dụng để tạo các hàm ẩn danh .
>>> (lambda x: x+2)(3)
5
3
vì nó được chuyển đến một chức năng. Các parens nằm xung quanh lambda sao cho biểu thức không được phân tích cú pháp lambda x: x+2(3)
là không hợp lệ vì 2
không phải là hàm.
Thêm một ví dụ về hàm sử dụng sort () với key = lambda. Hãy xem xét bạn có một danh sách các bộ dữ liệu. Trong mỗi bộ, bạn có một nhãn hiệu, mẫu mã và trọng lượng của xe và bạn muốn sắp xếp danh sách các bộ dữ liệu này theo nhãn hiệu, mẫu mã hoặc trọng lượng. Bạn có thể làm điều đó với lambda.
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]))
Các kết quả:
[('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)]
Vì việc sử dụng lambda đã được hỏi trong bối cảnh sorted()
, hãy xem điều này cũng https://wiki.python.org/moin/HowTo/Sorting/#Key_Fifts
Chỉ cần viết lại, khóa (Tùy chọn. Hàm để thực thi để quyết định thứ tự. Mặc định là Không có) trong các hàm được sắp xếp mong đợi một hàm và bạn sử dụng lambda.
Để xác định lambda, bạn chỉ định thuộc tính đối tượng bạn muốn sắp xếp và hàm được sắp xếp sẵn của python sẽ tự động chăm sóc nó.
Nếu bạn muốn sắp xếp theo nhiều thuộc tính thì gán key = lambda x: (property1, property2).
Để chỉ định thứ tự, chuyển ngược lại = true làm đối số thứ ba (Tùy chọn. Boolean. Sai sẽ sắp xếp tăng dần, True sẽ sắp xếp giảm dần. Mặc định là Sai) của hàm được sắp xếp.
Câu trả lời đơn giản và không tốn thời gian với một ví dụ liên quan đến câu hỏi được hỏi Thực hiện theo ví dụ này:
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"]))
Nhìn vào tên trong danh sách, chúng bắt đầu bằng D, B, C và A. Và nếu bạn chú ý độ tuổi, chúng là 55, 44, 33 và 22. Mã in đầu tiên
print(sorted(user, key=lambda el: el["name"]))
Kết quả cho:
[{'name': 'Abdullah', 'age': 22},
{'name': 'Ben', 'age': 44},
{'name': 'Citrus', 'age': 33},
{'name': 'Dough', 'age': 55}]
sắp xếp tên, bởi vì theo key = lambda el: el ["name"] chúng tôi đang sắp xếp tên và tên trả về theo thứ tự bảng chữ cái.
Mã in thứ hai
print(sorted(user, key= lambda y: y["age"]))
Kết quả:
[{'name': 'Abdullah', 'age': 22},
{'name': 'Citrus', 'age': 33},
{'name': 'Ben', 'age': 44},
{'name': 'Dough', 'age': 55}]
sắp xếp theo độ tuổi và do đó, danh sách trả về theo thứ tự tăng dần theo độ tuổi.
Hãy thử mã này để hiểu rõ hơn.
def
.