Синтаксис відсортованого (ключ = лямбда:…)


Відповіді:


162

keyце функція, яка буде викликана для перетворення елементів колекції перед їх порівнянням. Параметр передано доkey повинен бути чимось, на який можна дзвонити.

Використання lambdaстворює анонімну функцію (яку можна називати). У випадку з sortedпозивним приймається лише один параметр. Python lambdaдосить простий. Це може зробити лише одне і справді повернути.

Синтаксис lambda- це слово, lambdaза яким перелік імен параметрів, а потім єдиний блок коду. Список параметрів і блок коду позначаються двокрапкою. Це схоже на інші конструкції в пітона , а також такі , як while, for, ifі так далі. Всі вони є типовими блоками коду. Lambda - це ще один екземпляр заяви із блоком коду.

Ми можемо порівняти використання лямбда з використанням def для створення функції.

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

лямбда просто дає нам спосіб це робити, не призначаючи імені. Що робить його чудовим для використання в якості параметра для функції.

variable тут використовується двічі, тому що в лівій частині товстої кишки це ім'я параметра, а в правій частині він використовується в кодовому блоці для обчислення чогось.


10
Примітка (до ОП): слід уникати присвоювати лямбда імені (тобто використовувати його іншим способом, ніж як анонімну функцію). якщо ви виявите, що ви робите це, ви, ймовірно, просто повинні використовувати def.
Вім

151

Я думаю, що всі відповіді тут охоплюють суть того, що функція лямбда робить у контексті сортованого () досить добре, проте я все ще відчуваю, що опису, який призводить до інтуїтивного розуміння, бракує, тому ось мої два центи.

Для повноти я викладу очевидний фронт: sorted () повертає список відсортованих елементів, і якщо ми хочемо сортувати певним чином або якщо ми хочемо сортувати складний список елементів (наприклад, вкладені списки чи список кортежів) ми можемо викликати ключовий аргумент.

Для мене, інтуїтивне розуміння ключового аргументу, чому його потрібно викликати, і використання лямбда як функції (анонімної) дзвінки для виконання цього завдання складається з двох частин.

  1. Використання lamba в кінцевому підсумку означає, що вам не потрібно писати (визначати) цілу функцію, як, наприклад, один sblom, наданий приклад. Функції лямбда створюються, використовуються та негайно знищуються - так що вони не функціонують ваш код із більшою кількістю коду, який буде використаний лише один раз. Це, наскільки я розумію, є основною корисністю лямбда-функції, і її застосування для таких ролей є широким. Його синтаксис суто умовний, що по суті полягає в природі програмного синтаксису загалом. Вивчіть синтаксис і будьте з ним.

Синтаксис лямбда такий:

lambda 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'
  1. Ідея keyаргументу полягає в тому, що він повинен містити набір інструкцій, які по суті будуть вказувати на функцію 'sorted ()' на ті елементи списку, які слід використовувати для сортування. Коли він каже 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] # Чи має цей відсортований результат інтуїтивно зрозумілий для вас?

Зауважте, що моя лямбда-функція сказала сортувати, щоб перевірити, чи (е) парне чи непарне перед сортуванням.

АЛЕ ЗАЧЕКАЙТЕ! Ви можете (або, можливо, повинні) задатися питанням - по-перше, чому мої шанси виникають перед моїми евенями (оскільки моє ключове значення, здається, говорить про мою відсортовану функцію для визначення пріоритетності евеню за допомогою оператора мод у x%2==0). По-друге, чому мої евеню вийшли з ладу? 2 приходить до 6 правильно? Аналізуючи цей результат, ми дізнаємось дещо глибше про те, як працює аргумент сортованого () "ключа", особливо в поєднанні з функцією анонімної лямбда.

По-перше, ви помітите, що хоча шанси приходять до передів, самі єви не сортуються. Чому це?? Давайте читати документи :

Основні функції Починаючи з Python 2.4, і list.sort (), і сортування () додали ключовий параметр, щоб вказати функцію, яку потрібно викликати на кожному елементі списку перед порівнянням.

Ми мусимо трохи прочитати тут між рядками, але те, що це нам говорить, це те, що функція сортування викликається лише один раз, і якщо ми вкажемо ключовий аргумент, то сортуємо за значенням, на яке вказує нам функція ключа.

То що робить приклад із використанням модуля? Булева величина: True == 1, False == 0. Отже, як сортування справляється з цим ключем? Це в основному перетворює вихідний список у послідовності 1s і 0s.

[3,6,3,2,4,8,23] стає [0,1,0,1,1,1,0]

Тепер ми кудись дістаємось. Що ви отримуєте при сортуванні перетвореного списку?

[0,0,0,1,1,1,1]

Гаразд, тож тепер ми знаємо, чому шанси виникають перед переддень. Але наступне питання: Чому 6 все ще надходять до 2 у моєму остаточному списку? Ну це просто - це тому, що сортування відбувається лише один раз! тобто ті 1 все ще представляють вихідні значення списку, які знаходяться у вихідних положеннях відносно один одного. Оскільки сортування відбувається лише один раз, і ми не закликаємо будь-яку функцію сортування для упорядкування вихідних рівних значень від низьких до високих, ці значення залишаються у вихідному порядку відносно один одного.

Остаточне запитання - це таке: як я концептуально думаю про те, як порядок моїх булевих значень перетворюється на початкові значення, коли я роздруковую остаточний відсортований список?

Sorted () - це вбудований метод, який (цікавий факт) використовує гібридний алгоритм сортування, який називається Timsortякий поєднує аспекти сортування злиття та сортування вставки. Мені здається зрозумілим, що коли ви його називаєте, є механік, який зберігає ці значення в пам'яті і зв'язує їх зі своєю бульною ідентичністю (маскою), визначеною (...!) Лямбда-функцією. Порядок визначається їх булевою ідентичністю, розрахованою за лямбда-функцією, але майте на увазі, що ці підсписи (чиї та нулі) самі по собі не сортуються за своїми початковими значеннями. Отже, остаточний список, хоча він організований "Коефіцієнтами та Евенсом", не сортується за підспілом (евенти в цьому випадку вийшли з ладу). Справа в тому, що шанси впорядковані - це тому, що вони вже були впорядковані в первинному списку. Вихід з усього цього полягає в тому, що коли лямбда робить цю трансформацію, зберігається початковий порядок підсписок.

То як це все стосується початкового питання, і що ще важливіше, нашої інтуїції щодо того, як ми повинні реалізувати сортування () з його ключовим аргументом та лямбда?

Цю функцію лямбда можна розглядати як вказівник, який вказує на значення, за якими ми повинні сортувати, чи то вказівник, який відображає значення на булеве значення, перетворене функцією лямбда, або якщо його певний елемент у вкладеному списку, кортеж, диктант тощо, знову визначається функцією лямбда.

Дозвольте спробувати передбачити, що станеться, коли я запущу наступний код.

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])

Мій sortedдзвінок, очевидно, говорить: "Будь ласка, сортуйте цей список". Ключовий аргумент робить це трохи більш конкретним, кажучи, що для кожного елемента (x) у моєму списку повертають індекс 1 цього елемента, а потім сортують усі елементи вихідного списку 'mylist' за упорядкованим порядком списку, обчисленим за лямбда-функція. Оскільки у нас є список кортежів, ми можемо повернути індексований елемент із цього кортежу. Таким чином ми отримуємо:

[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]

Запустіть цей код, і ви побачите, що це наказ. Спробуйте індексувати список цілих чисел, і ви побачите, що код порушується.

Це було давно пояснене пояснення, але я сподіваюся, що це допомагає «сортувати» вашу інтуїцію щодо використання лямбда-функцій як ключового аргументу в сортованому () і далі.


8
відмінне і всебічне пояснення. Ця відповідь заслуговує 100 балів. Але мені цікаво, чому лайки менше відповідають на цю відповідь.
javed

3
Дякую за глибоке пояснення. Я читав документи та сортував інструкції, і мені не було зрозуміло ідея keyфункції. Якщо ви намагаєтесь зрозуміти sortedфункцію, то їх lambdaсинтаксис просто переходить на шлях розуміння.
Санбор

3
Це найкраще пояснення тут. Це було дуже корисно, щоб допомогти мені зрозуміти, як це насправді працює - я сортував функцію лямбда, але використовувати її в контексті сортування () не має сенсу. Це справді допомогло, дякую!
TGWaffles

2
Це геніальна відповідь. Вітаю вас, сер.
Раджеш Mappu

2
Це одна з моїх улюблених відповідей на переповнення стека. Дякую!
АдР

26

lambda- ключове слово Python, яке використовується для створення анонімних функцій .

>>> (lambda x: x+2)(3)
5

2
Чому навколо кожного є круглі дужки?
Крістофер Маркієта

19
Парени знаходяться навколо, 3тому що він передається функції. Парени знаходяться навколо лямбда, щоб вираз не розбирався як lambda x: x+2(3), що є недійсним, оскільки 2не є функцією.
Ігнасіо Васкес-Абрамс

Я не впевнений, що мені подобається термін "анонімні" функції. Я маю на увазі, правда, що вони не названі, тому анонім "технічно" точний. Я краще вважаю їх "тимчасовими функціями". Але потім, я педант.
користувач5179531

12

variableЗліва від :цього ім'я параметра. Використанняvariable справа - це використання параметра.

Значить майже точно так само, як:

def some_method(variable):
  return variable[0]

5

Ще один приклад використання сортованої () функції з ключем = лямбда. Розглянемо, у вас є список кортежів. У кожному кортежі у вас є марка, модель і вага автомобіля, і ви хочете сортувати цей список кортежів за маркою, моделлю або вагою. Можна зробити це з лямбда.

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)]

3

lambdaє анонімною функцією, а не довільною функцією. Параметр, який приймається, буде змінною, з якою ви працюєте, та стовпцем, в якому ви її сортуєте.



1

Просто перефразовуючи, клавіша (необов'язково. Функція, яку потрібно виконати для вирішення замовлення. За замовчуванням - немає) в сортованих функціях очікує функцію, і ви використовуєте лямбда.

Щоб визначити лямбда, ви вкажете властивість об'єкта, яку ви хочете сортувати, і вбудована функція сортування python автоматично забере його.

Якщо ви хочете сортувати за кількома властивостями, тоді призначте key = lambda x: (property1, property2).

Щоб вказати порядок замовлення, передайте reverse = true як третій аргумент (необов'язково. Булевий. False буде сортувати за зростанням, True буде сортувати по убуванню. За замовчуванням - False) відсортованої функції.


1

Проста і не вимагає багато часу відповідь із прикладом, що стосується поставленого запитання. Дотримуйтесь цього прикладу:

 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}]

сортує ім'я, тому що за допомогою ключа = lambda el: el ["ім'я"] ми сортуємо імена, а імена повертаються в алфавітному порядку.

Другий код друку

print(sorted(user, key= lambda y: y["age"]))

Результат:

[{'name': 'Abdullah', 'age': 22},
 {'name': 'Citrus', 'age': 33},
 {'name': 'Ben', 'age': 44}, 
 {'name': 'Dough', 'age': 55}]

сортує за віком, а отже, список повертається у порядку зростання за віком.

Спробуйте цей код для кращого розуміння.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.