Сортировка строк по длине - функциональная питона


Я пытаюсь портировать этот маленький Ф# фрагмент, останавливаясь весть:

["something"; "something else"; "blah"; "a string"] |> List.map (fun p -> p, p.Length) |> List.sortBy snd

В случае, если вы не говорите на языке F#, он получает длину каждой строки, затем сортирует по длине.

Выход:

[("blah", 4); ("a string", 8); ("something", 9); ("something else", 14)]

В Python, это лучшее, что я мог сделать до сих пор:

sorted([(p, len(p)) for p in ["something", "something else", "blah", "a string"]], key=lambda a:a[1])

А правильно, это не выглядит очень элегантно, а может это просто моя не весть глаз.

Это подходящие для Python код? Как бы вы это пишите? Может быть, императивный стиль является более целесообразным?



Комментарии
4 ответа

data = ["something", "something else", "blah", "a string"]
result = [(x, len(x)) for x in sorted(data, key = len)]

В основном, более простой для сортировки первого, то украсить. Хотя, я не уверен, почему вы должны были длины списка в ваш кортеж. Если вам не нужна сортировка по длина может быть намного короче.

Редактировать:

Если все, что я хотел был, чтобы выводить данные, я бы сделал это так:

for string in sorted(data, key = len):
print string, len(string)

Если вы действительно хотели ликвидировать две ссылки на лен, вы могли бы сделать:

mykey = len
for string in sorted(data, key = mykey):
print string, mykey(string)

Но если вы не повторное использование кода с разных системы MyKey, что не кажется стоящим.

29
ответ дан 26 февраля 2011 в 12:02 Источник Поделиться

Я не думаю, что ваше решение выглядит плохо. Я бы, наверное, использовать временную переменную, чтобы длина линии немного более читабельным. Вы могли бы рассмотреть itemgetter от оператора модуля.

Е. Г.

from operator import itemgetter

orig_list = ["something", "something else", "blah", "a string"]
mylist = [(p, len(p)) for p in orig_list]
mylist.sort(itemgetter(1))

Лично я думаю, что это просто, как читается.

mylist = sorted([(p, len(p)) for p in orig_list], key=itemgetter(1))

6
ответ дан 26 февраля 2011 в 12:02 Источник Поделиться

Если вы не хотите называть лен дважды для каждого элемента (если, например, вам нужно позвонить некоторые дорогостоящие функции, а не лен), можно отсортировать по второму пункту без лямбд с помощью itemgetter.

from operator import itemgetter    

data = ["something", "something else", "blah", "a string"]
l = [(s, len(s)) for s in data]
l.sort(key = itemgetter(1))

Однако, если порядок элементов не важен, было бы лучше разместить сначала длина в кортеж, потому что поведение по умолчанию для сортировки кортежей сравнивать элементы по порядку.

data = ["something", "something else", "blah", "a string"]
l = sorted((len(s), s) for s in data)

Затем вы можете переключаться между ними во время выхода, если вы хотите:

for length, item in l:
print item, length

5
ответ дан 4 марта 2011 в 07:03 Источник Поделиться

Вот еще один вариант. За ключевую функцию, он определяет лямбда-выражение, которое принимает два элемента последовательности, и распаковывает двух предметов на "S" и "L", а возвращает "л". Это позволяет избежать ковыряться каждый (строка, длина) пара магическое число, а также обеспечивает немного ограничение типа на предметы для сортировки. Кроме того, он разбивает строки в удобных местах, что вполне законно в Python:

sorted([(p, len(p)) for p 
in ("something",
"something else",
"blah",
"a string")],
key=lambda (s, l): l)

А вот версия, которая использует генератор осознание вместо понимания списка. Выражений генератор оцениваются как элементы берутся из них, а не все сразу. В этом примере нет никакого преимущества, но при использовании выражения, в котором элементы являются дорогостоящими, чтобы создать, или где итерации могут быть прекращены досрочно (например, запросы к базе данных), генераторы-это большая победа:

sorted(((p, len(p)) for p 
in ("something",
"something else",
"blah",
"a string")),
key=lambda (s, l): l)

И эта версия детерминировано обрабатывает случаи, когда существует некоторая неопределенность по сортировки только по длине:

sorted(((p, len(p)) for p 
in ("something",
"something else",
"four things",
"five things",
"a string")),
key=lambda (s, l): (l, s))

1
ответ дан 1 марта 2011 в 06:03 Источник Поделиться