Народ, объясните принцип сортировки по ключу

333 views
Skip to first unread message

ashdesigner

unread,
Feb 16, 2012, 11:10:24 AM2/16/12
to Пишем на Python лучше
Добрый вечер!

Прошу прощения за банальный с точки зрения проф. программиста вопрос -
но все же)) Я никак не могу понять, как работает в Питоне сортировка
списков по ключу.

У меня в примерах есть два варианта кода, которые оба работают, но
взрывают мне мозг, потому что я никак не могу понять, как - и почему у
них разное количество входных параметров:

Вариант 1:

def my_key(item):
return (item[1], item[3])

to_sort.sort(key=my_key)

Вариант 2:

sortList.sort(key = lambda (listKey, listValue): listKey)

Объясните, пожалуйста, на пальцах и конкретных примерах списков, как
это работает и как это может быть применено в реальной практике.

Заранее благодарен!

Антон

Sergey Schetinin

unread,
Feb 16, 2012, 11:15:02 AM2/16/12
to better-p...@googlegroups.com
lambda (listKey, listValue): listKey

это

def func((listKey, listValue)):
return listKey

а не

def func(listKey, listValue):
return listKey

как могло бы показаться.

То есть

sortList.sort(key = lambda (listKey, listValue): listKey)

идентично

sortList.sort(key=lambda v: v[0])

2012/2/16 ashdesigner <antony....@gmail.com>:

> --
> Группа: http://groups.google.com/group/better-python-ru
> Отписка: better-python-...@googlegroups.com

ashdesigner

unread,
Feb 16, 2012, 12:00:26 PM2/16/12
to Пишем на Python лучше
Сергей, спасибо, отлично!

Теперь по первому вопросу все встало, наконец, на свои места.

И еще один вопрос - правда, его, наверное, нужно было первым задавать:
а какой вообще смысл в использовании key? Можно привести какой-то
реальный жизненный пример?

On 16 фев, 20:15, Sergey Schetinin <mal...@gmail.com> wrote:
> lambda (listKey, listValue): listKey
>
> это
>
> def func((listKey, listValue)):
>   return listKey
>
> а не
>
> def func(listKey, listValue):
>   return listKey
>
> как могло бы показаться.
>
> То есть
>
> sortList.sort(key = lambda (listKey, listValue): listKey)
>
> идентично
>
> sortList.sort(key=lambda v: v[0])
>

> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 12:04:12 PM2/16/12
to better-p...@googlegroups.com
Например для того чтобы использовать нестандартное сравнение

>>> x = ['b', 'aa']
>>> x.sort()
>>> x
['aa', 'b']
>>> x.sort(key=len)
>>> x
['b', 'aa']

по-умолчанию строки сравниваются лексикографически, а в этом примере я
отсортировал по длине.

В общем это очень полезная фича.

2012/2/16 ashdesigner <antony....@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 12:09:48 PM2/16/12
to Пишем на Python лучше
То есть, получается, что

sortList.sort(key=lambda v: v[0])

фактически идентично

sortList.sort()

...поскольку сравнивает элементы (в данном случае - индексы значений)
между собой алгоритмом по умолчанию (от меньшего к большему)?

On 16 фев, 21:04, Sergey Schetinin <mal...@gmail.com> wrote:
> Например для того чтобы использовать нестандартное сравнение
>
> >>> x = ['b', 'aa']
> >>> x.sort()
> >>> x
> ['aa', 'b']
> >>> x.sort(key=len)
> >>> x
>
> ['b', 'aa']
>
> по-умолчанию строки сравниваются лексикографически, а в этом примере я
> отсортировал по длине.
>
> В общем это очень полезная фича.
>

> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 12:13:56 PM2/16/12
to better-p...@googlegroups.com
(каждое сообщение заново приходится подтверждать, что за беда =\ )

В общем-то да. Если считать что в sortList кортежи а не скажем
какие-то мутные обьекты которые поддерживают итерацию но
переопределяют сравнение на какую-то муть. Короче говоря скорее всего
можно key=.. опустить.

2012/2/16 ashdesigner <antony....@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 12:12:01 PM2/16/12
to Пишем на Python лучше
А, нет, не идентично, поскольку сравнивает индексы, а не значения.

Получается, что

sortList.sort(key=lambda v: v[0])

никогда не изменит порядок значений в массиве?

Sergey Schetinin

unread,
Feb 16, 2012, 12:16:08 PM2/16/12
to better-p...@googlegroups.com
Почему же не изменит, изменит.

(email antony....@gmail.com кажется не подписан на группу, из-за
этого про каждое сообщение админка переспрашивает, попробуйте
подписать именно этот адрес)

2012/2/16 ashdesigner <antony....@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 12:18:23 PM2/16/12
to better-p...@googlegroups.com
Суть в том, что кортежи (тюплы) сравниваются лексикографически, т.е.
сначала первые элементы, и только если они равны -- вторые. Т.е.
результат сравнения пар ключ-значение будет таким же как и у сравнения
просто ключей (при условии что ключи не равны).

2012/2/16 Sergey Schetinin <mal...@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 12:23:24 PM2/16/12
to Пишем на Python лучше
Хорошо, чтобы до меня окончательно дошло, где ключ, а где значение:

Например, мы имеем такие варианты:

listA = ['a', 'c', 'b']
listB = ['a', 'cc', 'bbb']
listC = [('one', 'two'), ('three', 'four')]

Что будет являться ключом, а что - значением в каждом из случаев при
сортировке?

On 16 фев, 21:18, Sergey Schetinin <mal...@gmail.com> wrote:
> Суть в том, что кортежи (тюплы) сравниваются лексикографически, т.е.
> сначала первые элементы, и только если они равны -- вторые. Т.е.
> результат сравнения пар ключ-значение будет таким же как и у сравнения
> просто ключей (при условии что ключи не равны).
>
> 2012/2/16 Sergey Schetinin <mal...@gmail.com>:
>
>
>
>
>
>
>
> > Почему же не изменит, изменит.
>

> > (email antony.shash...@gmail.com кажется не подписан на группу, из-за


> > этого про каждое сообщение админка переспрашивает, попробуйте
> > подписать именно этот адрес)
>

> > 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 12:30:38 PM2/16/12
to better-p...@googlegroups.com
Эмм.. ну вообще тут путаница. Изначально ключем был назван первый
аргумент в лямбде в первом вопросе. Это не имеет никакого отношения к
параметру key у сортировки. В общем только listC подходит для
сортировки из примера и ключи понятно 'one' и 'three'

2012/2/16 ashdesigner <antony....@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 12:52:48 PM2/16/12
to Пишем на Python лучше
Сергей, как тогда отсортировать listB, чтобы он стал таким:

a, bbb, ccc

?

On 16 фев, 21:30, Sergey Schetinin <mal...@gmail.com> wrote:
> Эмм.. ну вообще тут путаница. Изначально ключем был назван первый
> аргумент в лямбде в первом вопросе. Это не имеет никакого отношения к
> параметру key у сортировки. В общем только listC подходит для
> сортировки из примера и ключи понятно  'one' и 'three'
>

> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 12:54:09 PM2/16/12
to better-p...@googlegroups.com
просто .sort()

2012/2/16 ashdesigner <antony....@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 1:05:08 PM2/16/12
to Пишем на Python лучше
Так, все, до меня дошло, кажется. Проверил - работает))

Имеем:

sortList = ['a', 'cc', 'bbb']

def sortByAlphabet(a):
return a[0] # ключ сортировки - первая буква каждой строки

def sortByLength(a):
return len(a) # ключ сортировки - длина каждой строки

sortList.sort(key=sortByAlphabet)
print sortList

# >>> ['a', 'bbb', 'cc']

sortList.sort(key=sortByLength)
print sortList

# >>> ['a', 'cc', 'bbb']

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

Ура, заработало. Спасибо, Сергей!))

On 16 фев, 21:54, Sergey Schetinin <mal...@gmail.com> wrote:
> просто .sort()
>
> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 1:07:24 PM2/16/12
to better-p...@googlegroups.com
2012/2/16 ashdesigner <antony....@gmail.com>:

> Так, все, до меня дошло, кажется. Проверил - работает))
>
> Имеем:
>
> sortList = ['a', 'cc', 'bbb']
>
> def sortByAlphabet(a):
>        return a[0] # ключ сортировки - первая буква каждой строки
>
> def sortByLength(a):
>        return len(a) # ключ сортировки - длина каждой строки
>
> sortList.sort(key=sortByAlphabet)
> print sortList
>
> # >>> ['a', 'bbb', 'cc']
>
> sortList.sort(key=sortByLength)
> print sortList
>
> # >>> ['a', 'cc', 'bbb']
>
> Таким образом, ключ key определяет, какие именно свойства каждого из
> перебираемых элементов мы сравниваем. Сортировка по умолчанию идет от
> меньшего к большему.

Да, всё правильно.

> Ура, заработало. Спасибо, Сергей!))

На здоровье.

ashdesigner

unread,
Feb 16, 2012, 1:09:33 PM2/16/12
to Пишем на Python лучше
p.s. Не пойму только одного: почему такие простые вещи нигде в
документации так просто не описаны? Зачем усложнять?))

On 16 фев, 22:07, Sergey Schetinin <mal...@gmail.com> wrote:
> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

Sergey Schetinin

unread,
Feb 16, 2012, 1:23:23 PM2/16/12
to better-p...@googlegroups.com
Хм. Я не помню как именно задокументирована именно эта фича, и в целом
текст документации по Питону в основном достаточно хорош, но если
говорить в общем, то документация действительно часто бывает усложнена
без нужды.

Я бы сказал больше, если у проблемы есть два варианта решения --
простой и не требующих пояснений и сложный и требующий множества
документации, то второй окажется более популярным, просто потому что
на него легче наткнуться -- "сети" документации раскинуты шире, есть
всякие комьюнити, тонны блогов, рецептов, учителей, тренингов итд.
(См. например Джанго, Agile и прочий шлак).

Ну и пишушие документацию тоже хотят показать какие они умные, какие
непростые вещи они обьясняют, потому и доки пишутся сложными сами
собой.

2012/2/16 ashdesigner <antony....@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 1:48:16 PM2/16/12
to Пишем на Python лучше
Я о том же. И когда мозг совсем запутался, приходится напрягать людей
и задавать глупые вопросы - хотя все, на самом деле, лежит на
поверхности.

Я считаю, что программирование как технология должно быть максимально
простым, потому что этим инструментом решаются и без того сложные
задачи. Это как, например, чудовищный синтаксис Objective C, один
взгляд на который приводит в ужас - однако все это безобразие
позиционируется как философия для избранных, ё-маё-куда-деваться))
Если тебе нужно решить сложную задачу, инструменты не должны отнимать
столько же времени на изучение, сколько и сама работа. Они должны быть
максимально простыми и понятными. Выражаясь словами Энштейна, "если ты
не можешь объяснить что-либо просто, значит, ты этого до конца не
понимаешь".

Кстати, за такие же точно "косяки" - усложнение на пустом месте - я не
перевариваю и лженауку философию, но это уже другая тема))

On 16 фев, 22:23, Sergey Schetinin <mal...@gmail.com> wrote:
> Хм. Я не помню как именно задокументирована именно эта фича, и в целом
> текст документации по Питону в основном достаточно хорош, но если
> говорить в общем, то документация действительно часто бывает усложнена
> без нужды.
>
> Я бы сказал больше, если у проблемы есть два варианта решения --
> простой и не требующих пояснений и сложный и требующий множества
> документации, то второй окажется более популярным, просто потому что
> на него легче наткнуться -- "сети" документации раскинуты шире, есть
> всякие комьюнити, тонны блогов, рецептов, учителей, тренингов итд.
> (См. например Джанго, Agile и прочий шлак).
>
> Ну и пишушие документацию тоже хотят показать какие они умные, какие
> непростые вещи они обьясняют, потому и доки пишутся сложными сами
> собой.
>

> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

> ...
>
> продолжение >>

Sergey Schetinin

unread,
Feb 16, 2012, 2:02:04 PM2/16/12
to better-p...@googlegroups.com
Это не касается вопроса про .sort(key=..) но поэтому же чаще всего
читать код лучше чем документацию, потому что приемлемо написанный код
описывает что же он делает куда более прямо чем документация. Более
того, код может ответить на вопросы, про которые доки умалчивают итд
итп. Так не нужно удерживать в голове и реальность и то что про неё
говорит документация )


2012/2/16 ashdesigner <antony....@gmail.com>:

ashdesigner

unread,
Feb 16, 2012, 3:10:51 PM2/16/12
to Пишем на Python лучше
Зарегился и запостил тему на хабре - может, опубликуют.

On 16 фев, 23:02, Sergey Schetinin <mal...@gmail.com> wrote:
> Это не касается вопроса про .sort(key=..) но поэтому же чаще всего
> читать код лучше чем документацию, потому что приемлемо написанный код
> описывает что же он делает куда более прямо чем документация. Более
> того, код может ответить на вопросы, про которые доки умалчивают итд
> итп. Так не нужно удерживать в голове и реальность и то что про неё
> говорит документация )
>

> 2012/2/16 ashdesigner <antony.shash...@gmail.com>:

> ...
>
> продолжение >>

Vladimir

unread,
Feb 16, 2012, 3:28:58 PM2/16/12
to better-p...@googlegroups.com
в песочницу? покажешь, поставлю плюс

16 февраля 2012 г. 22:10 пользователь ashdesigner <antony....@gmail.com> написал:
> ...
>
> продолжение >>

Sergey Schetinin

unread,
Feb 16, 2012, 3:50:14 PM2/16/12
to better-p...@googlegroups.com
Хм, раз пошла такая жара, дайте инвай чтоли? )

2012/2/16 Vladimir <tv.v...@gmail.com>:

ashdesigner

unread,
Feb 17, 2012, 2:08:32 PM2/17/12
to Пишем на Python лучше
Ребят, запостил вчера, но пока что хабр мне не отписался. Сообщение в
ответ на мой пост сказало, мол, наберитесь терпения - вам ответят на
почту))
Сегодня и почта пустая, и в песочнице публикации нет.

Поскольку на хабре я новичок, то было бы неплохо получить ваши голоса
или даже инвайт)) Ну, если пост захабрят, конечно.

Антон

On 17 фев, 00:50, Sergey Schetinin <mal...@gmail.com> wrote:
> Хм, раз пошла такая жара, дайте инвай чтоли? )
>

> 2012/2/16 Vladimir <tv.vl...@gmail.com>:


>
>
>
>
>
>
>
> > в песочницу? покажешь, поставлю плюс
>
> > 16 февраля 2012 г. 22:10 пользователь ashdesigner

> > <antony.shash...@gmail.com> написал:

> ...
>
> продолжение >>

ashdesigner

unread,
Feb 20, 2012, 4:08:30 AM2/20/12
to Пишем на Python лучше
Всем привет!

Мне дали приглашение на хабр - и запостили мою заметку:

http://habrahabr.ru/blogs/python/138535/

Комментируйте, если есть желание)) И, конечно же, большое спасибо
Сергею за помощь!

> ...
>
> продолжение >>

Vladimir

unread,
Feb 20, 2012, 4:11:01 AM2/20/12
to better-p...@googlegroups.com
поздравляю +1

20 февраля 2012 г. 11:08 пользователь ashdesigner <antony....@gmail.com> написал:
> ...
>
> продолжение >>

Sergey Schetinin

unread,
Feb 20, 2012, 4:15:53 AM2/20/12
to better-p...@googlegroups.com
У меня инвайта нет, поэтому камент оставить не могу. В общем вместо
sortList.sort(key=sortByLength) можно (и лучше) писать
sortList.sort(key=len) это и короче и понятней и быстрее

2012/2/20 Vladimir <tv.v...@gmail.com>:

Reply all
Reply to author
Forward
0 new messages