2009-08-01 2 views
28

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

Пример:

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

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

Спасибо большое за любой Помогите!

ответ

33

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

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

key argument функции 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] 
+1

Как только я задал вопрос, у меня появилось прозрение и в основном придумал то же самое, кроме лямбды (еще не узнал о них). Просто написал мою собственную функцию cmp, которая берет tupples из dict.items() и возвращает результат. То же самое, просто другой способ написать это. Большое спасибо за быстрый ответ! – jay

+0

Отличное решение. Мне нравится простота 'sorted()'. –

+4

Я думаю, что это немного яснее: sorted (myDict.items(), key = lambda (k, v): v [2]) –

2

Вы заявили две совершенно разные хочет:

  1. «То, что я хочу сделать, это своего рода словарь списков ...»
  2. „Я хочу, чтобы иметь возможность перебора по словарю в порядке ...“

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

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

  1. Возьмите копию словаря содержимого (который будет довольно неупорядоченный)
  2. Сортировать что
  3. перебрать отсортированных результатов - и у вас уже есть два решения для этого. Кстати, решение, которое использует «ключ» вместо «cmp», лучше; см sorted

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

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

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; 
2

Как Иоанн Махлин сказал, что вы не можете сортировать словарь 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()])] 

... это список понимание делает undecorate из отсортированного списка кортежей, который возвращается внутренним списком понимания. Внутреннее понимание создает набор кортежей, желаемый ключ сортировки (третий элемент списка) и ключ словаря, соответствующий клавише сортировки. 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]) 

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

+0

(1) Вы сравниваете decorate-sort-undecorate с использованием cmp arg, а введение ключа arg отрубало очень большой фрагмент территории DSU. (2) Ваше решение оставляет OP со списком диктофоны ... чтобы получить то, что он хочет, ему придется сделать еще один цикл элементов dict (3), ваш верный способ имеет опечатку: s/v [2],/v [2], k / –

Смежные вопросы