Смущает сортировка (..., ключ = лямбда ...) - PullRequest
0 голосов
/ 04 января 2019

Может кто-нибудь объяснить, пожалуйста, эти лямбды? Я довольно смущен следующим кодом и был бы признателен за помощь в понимании кода от кого-то, кто знает об этом и может разбить код на понятные компоненты.

convert = lambda text: int(text) if text.isdigit() else text
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(l, key = alphanum_key)

(источник: https://arcpy.wordpress.com/2012/05/11/sorting-alphanumeric-strings-in-python/)

Я понимаю первую лямбду.

Для второй лямбды alphanum_key Я в замешательстве. Кажется, что ключ передается в лямбду и используется в функции split() в модуле re, но я не вижу, чтобы key передавался в лямбду alphanum_key, когда эта лямбда вызывается в sorted() функция.

Я написал небольшую программу, чтобы посмотреть, смогу ли я создать нормальные def функции из лямбд, которые явно используют плохую форму, возвращая значения и вызываясь как функции. Вот мой код:

import re

def convert2(text):
    if text.isdigit():
        return int(text)
    else:
        return text

def alphanum_key2(key):
    a_list = []
    for i in re.split('([0-9]+)', key):
        a_list.append(convert2(i))

    return a_list


if __name__ == "__main__":
    things = ["10bags", "500miles", "10000maniacs", "2000lightYearsFromHome"]
    x = sorted(things, key= alphanum_key2)
    print(x)
    #This prints
    #['10bags', '500miles', '2000lightYearsFromHome', '10000maniacs']

    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
    print(sorted(things, key = alphanum_key))
    #This prints
    #['10bags', '500miles', '2000lightYearsFromHome', '10000maniacs']

Это приводит ко второму вопросу ... Почему нормальные def функции, которые имитируют лямбда-функции, возвращают разные и неверные результаты. Обратите внимание на результаты, возвращенные в комментариях к коду, если вы не хотите запускать эту программу на своем компьютере.

1 Ответ

0 голосов
/ 05 января 2019

Вы говорите, что понимаете первую функцию convert, поэтому я не буду вдаваться в подробности; просто знайте, что он возвращает либо строку, либо целое число.

Прямое преобразование второго из лямбда-выражений:

def alphanum_key(key):
    return [convert(c) for c in re.split('([0-9]+)', key)]

Давайте разберемся с этим.

[... for ...]

Это понимание списка. Он создаст список, содержащий элемент для каждой итерации for.

re.split('([0-9]+)', key)

При этом используется регулярное выражение, состоящее из всех цифр ([0-9]), повторенных один или несколько раз (+). Поместив скобки вокруг этого выражения, эти совпадения будут включены в выходные данные split.

>>> re.split('([0-9]+)', "10bags")
['', '10', 'bags']

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

Окончательный результат alphanum_key будет ['', 10, 'bags'], поскольку '10' будет преобразовано в целое число 10. Это важно, потому что вы хотите сравнить цифры:

>>> '10000' < '500'
True
>>> 10000 < 500
False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...