2013-03-30 2 views
2

У меня есть словарь, как это:Python: сортировка многоуровневого словаря по части ключ

{ 
    '28.10.11/D/text1/' : {key:value1}, 
    '27.01.11/D/text2/' : {key:value2}, 
    '07.11.12/D/text3/' : {key:value3} 
} 

Часть ключа на основе даты, что набор в формате «% d% M% Y.».. Необходимо отсортировать все словарные ключи по дате. Значение должно быть сохранено в том же формате. Пример:

{ 
    '27.01.11/D/text2/' : {key:value2}, 
    '28.10.11/D/text1/' : {key:value1}, 
    '07.11.12/D/text3/' : {key:value3} 
} 
+1

Словари не имеют порядка и поэтому не могут быть отсортированы. Вы хотите, чтобы на выходе был список кортежей '(key, value)? –

+0

Не знал об этом. Хорошо, измените его на список. Благодаря! – Apache

ответ

4

Вы не можете сортировать стандартный словарь, но можете сортировать и отображать элементы.

from datetime import datetime 

D = {'28.10.11/D/text1/' : {'key':'value1'}, 
    '27.01.11/D/text2/' : {'key':'value2'}, 
    '07.11.12/D/text3/' : {'key':'value3'}} 

for k in sorted(D,key=lambda k: datetime.strptime(k[:8],"%d.%m.%y")): 
    print(k,D[k]) 

Выход:

27.01.11/D/text2/ {'key': 'value2'} 
28.10.11/D/text1/ {'key': 'value1'} 
07.11.12/D/text3/ {'key': 'value3'} 

Если вы хотите использовать список:

from datetime import datetime 
from pprint import pprint 

L = [('28.10.11/D/text1/' , {'key':'value1'}), 
    ('27.01.11/D/text2/' , {'key':'value2'}), 
    ('07.11.12/D/text3/' , {'key':'value3'})] 

L.sort(key=lambda k: datetime.strptime(k[0][:8],"%d.%m.%y")) 
pprint(L) 

Выход:

[('27.01.11/D/text2/', {'key': 'value2'}), 
('28.10.11/D/text1/', {'key': 'value1'}), 
('07.11.12/D/text3/', {'key': 'value3'})] 

Наконец, если вы все еще хотите словарю поведение, в OrderedDict помнит, что ключи заказа вставлены, поэтому:

from collections import OrderedDict 
from datetime import datetime 
from pprint import pprint 

D = {'28.10.11/D/text1/' : {'key':'value1'}, 
    '27.01.11/D/text2/' : {'key':'value2'}, 
    '07.11.12/D/text3/' : {'key':'value3'}} 

OD = OrderedDict(sorted(D.items(), 
       key=lambda k: datetime.strptime(k[0][:8],"%d.%m.%y")) 
pprint(OD) 

Выход:

{'27.01.11/D/text2/': {'key': 'value2'}, 
'28.10.11/D/text1/': {'key': 'value1'}, 
'07.11.12/D/text3/': {'key': 'value3'}} 
+0

очень приятно. python awsome – WeaselFox

+0

Хороший ответ! Возможно, было бы полезно объяснить вашу «лямбду» немного больше. –

+0

Объяснение лямбда: Возьмите первые восемь символов: 'k [: 8]' и разделите их на.. 'В список:' .split ('.') ', А затем отмените список:' [:: - 1] '. Будет работать так же, как это: 'list (reverse (k [: 8] .split ('.'))) ' – hughdbrown

2

Outline

Использование sorted функция key аргумента. Напишите функцию key, которая преобразует строку в Datetime и сортирует на основе Datetime.

Код

def remap_key(key): 
    from datetime import datetime 
    a = key.split('/')[0] 
    return datetime.strptime(a, "%d.%m.%y") 

Результат

>>> d = { 
... '27.01.11/D/text2/' : "a", 
... '28.10.11/D/text1/' : "b", 
... '07.11.12/D/text3/' : "c" 
... } 
>>> 
>>> def remap_key(key): 
...  from datetime import datetime 
...  a = key.split('/')[0] 
...  return datetime.strptime(a, "%d.%m.%y") 
... 
>>> sorted(d, key=remap_key) 
['27.01.11/D/text2/', '28.10.11/D/text1/', '07.11.12/D/text3/'] 

Или сортировать по iteritems:

>>> def remap_key(key_pair): 
...  from datetime import datetime 
...  key = key_pair[0] 
...  a = key.split('/')[0] 
...  return datetime.strptime(a, "%d.%m.%y") 
... 
>>> sorted(d.iteritems(), key=remap_key) 
[('27.01.11/D/text2/', 'a'), ('28.10.11/D/text1/', 'b'), ('07.11.12/D/text3/', 'c')] 
1

В качестве другого варианта, вы можете использовать OrderedDict в сочетании с DateTime (как уже упоминалось hughdbrown) :

>>> from collections import OrderedDict 
>>> from datetime import datetime 
>>> d = { 
    '28.10.11/D/text1/' : {'key1':'value1'}, 
    '27.01.11/D/text2/' : {'key2':'value2'}, 
    '07.11.12/D/text3/' : {'key3':'value3'} 
} 
>>> OrderedDict(sorted(d.items(), key=lambda t: datetime.strptime(t[0][:8], "%d.%m.%y"))) 

Результат:

OrderedDict([('27.01.11/D/text2/', {'key2': 'value2'}), ('28.10.11/D/text1/', {'key1': 'value1'}), ('07.11.12/D/text3/', {'key3': 'value3'})]) 

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

+0

Регулярное выражение с группировкой для отмены порядок матчей немного неясен. Это дата! Почему бы не использовать «Datetime» в качестве ключа? 'OrderedDict (sorted (d.items(), key = lambda t: datetime.strptime (t [0] [: 8],"% d.% M.% Y ")))' – hughdbrown

+0

Хорошая точка. Я изменю его соответствующим образом. –

+0

+1 Удачи вам в этом ответе. – hughdbrown