Подтвердить что ты не робот

Python: сортировка словаря списков

Продолжаем учиться python (наконец!) и пока не могу полностью обмануть его. То, что я хочу сделать, - сортировать словарь списков по значению, используя третий элемент в списке. Это довольно просто сортировка словаря по значению, когда значение представляет собой только один номер или строку, но этот список вещей меня озадачил.

Пример:

myDict = { 'item1' : [ 7, 1, 9], 'item2' : [8, 2, 3], 'item3' : [ 9, 3, 11 ] }

Я хочу, чтобы иметь возможность итерации через словарь в порядке третьего значения в каждом списке, в этом случае 9, 3, 11.

Большое спасибо за любую помощь!

4b9b3361

Ответ 1

Вот один из способов сделать это:

>>> sorted(myDict.items(), key=lambda e: e[1][2])
[('item2', [8, 2, 3]), ('item1', [7, 1, 9]), ('item3', [9, 3, 11])]

key аргумент функции sorted позволяет получить ключ сортировки для каждого элемента списка.

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

>>> for key, value in sorted(myDict.items(), key=lambda e: e[1][2]):
...   print key, value
... 
item2 [8, 2, 3]
item1 [7, 1, 9]
item3 [9, 3, 11]

Ответ 2

Вы указали два совершенно разных желания:

  • "Я хочу сделать, это отсортировать словарь списков..."
  • "Я хочу, чтобы иметь возможность итерации через словарь в порядке..."

Первое из них по определению невозможно - для сортировки что-то подразумевает перестановку в некотором порядке. Словари Python по своей сути неупорядочены. Второй вариант будет смутно возможен, но вряд ли будет реализован.

Что вы можете сделать, это

  • Возьмите копию содержимого словаря (что будет довольно неупорядоченный)
  • Сортировка
  • Итерации по отсортированным результатам - и у вас уже есть два решения для этого. Кстати, решение, в котором вместо этого используется "ключ" "cmp" лучше; см. sorted

"третий элемент в списке" пахнет "третьим элементом в кортеже" для меня, и "e [1] [2]" просто пахнет:-)... вам может понравиться исследовать использование названных кортежей вместо списков; см. с именем tuple factory

Если вы собираетесь часто делать извлечение/сортировку/процесс на больших наборах данных, вам может понравиться что-то подобное, используя модуль sqlite3, поставляемый Python:

create table ex_dict (k text primary key, v0 int, v1 int, v2 int);
insert into ex_dict values('item1', 7, 1, 9);
-- etc etc 
select * from ex_dict order by v2;

Ответ 3

Как сказал Джон Махлин, вы не можете сортировать словарь Python.

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

Предпочтительный шаблон Python (идиома) для сортировки по любому альтернативному критерию называется "украсить-сортировать-undecorate" (DSU). В этой идиоме вы создаете временный список, который содержит кортежи вашего ключа (ов), за которыми следуют ваши исходные элементы данных, а затем вызовите обычный .sort() метод в этом списке (или, в более поздних версиях Python просто оберните украшение в вызываемой функции отсортированной()). Затем вы удаляете "украшения".

Причина, по которой это обычно предпочтительнее, чем передача функции сравнения методу .sort(), заключается в том, что встроенный код сортировки по умолчанию Python (скомпилированный C в обычном C Python) очень быстрый и эффективный в случае по умолчанию, но намного, намного медленнее, когда ему приходится многократно называть код объекта Python, много раз в случае, отличном от стандартного. Поэтому обычно гораздо лучше выполнять итерацию данных, создающих структуры данных, которые могут быть переданы в стандартные процедуры сортировки.

В этом случае вы сможете использовать что-то вроде:

[y[1] for y in sorted([(myDict[x][2], x) for x in myDict.keys()])]

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

Более подробный способ сделать это может быть легче читать:

temp = list()
for k, v in myDict.items():
    temp.append((v[2],))
temp.sort()
results = list()
for i in temp:
    results.append(i[1])

Обычно вы должны создавать такой код итеративно, в интерпретаторе, используя небольшие образцы данных. Постройте выражение "украсить" или функцию. Затем оберните это при вызове sorted(). Затем создайте выражение undecorate (которое обычно так же просто, как показано здесь).