2013-04-03 3 views
6

Скажем, у меня есть словарь королей с римскими цифрами в их именах в качестве ключа, римские цифры в целочисленной форме как значения.Python: сортировка элементов в словаре частью ключа?

d = {'Zemco III': 3, 'Usamec XL': 40, 'Usamec VII': 7, 'Robert VIII': 8, 'Usamec XLII': 42, 'Mary XXIV': 24, 'Robert III': 3, 'Robert XV': 15, 'Usamec XLIX': 49}

Я хотел бы отсортировать список из старейших в младшей, то есть Usamec XLII должны прийти до Usamec XLIX. Я также хотел бы отсортировать список по алфавиту, то есть Usamec XLII должен появиться перед Zemco III.

Мой подход был сортировать по имени первого, затем римские цифры значения, как, например:

x = sorted(d.items(),key=operator.itemgetter(0)) 
y = sorted(x,key=operator.itemgetter(1)) 

Однако, поскольку римские цифры являются частью ключа, мой алфавитный сортировки не работает должным образом. Мой вопрос: могу ли я отсортировать словарь по части ключа, например, если моим ключом является Zemco III, могу ли я отсортировать элементы как-то с key.split() [0] вместо всего ключа? Благодаря!

ответ

2

key - это просто функция, которая получает элемент и возвращает то, что вам нужно сортировать. Это может быть что угодно.

Это сортирует элементы по (name_without_rightmost_word, number) ключа:

In [92]: sorted(d.items(), key=lambda (name, num): (name.rsplit(None, 1)[0], num)) 
Out[92]: 
[('Mary XXIV', 24), 
('Robert III', 3), 
('Robert VIII', 8), 
('Robert XV', 15), 
('Usamec VII', 7), 
('Usamec XL', 40), 
('Usamec XLII', 42), 
('Usamec XLIX', 49), 
('Zemco III', 3)] 

Если вы используете Python 3, используйте этот key:

lambda item: (item[0].rsplit(None, 1)[0], item[1]) 

 

key.rsplit(None, 1)[0] лучше key.split()[0] в случае многословные имена.

+0

Это сработало. Спасибо, Павел! – 2013-04-03 19:42:49

+0

В качестве последующего вопроса, что, если мой словарь был заказан, чтобы число было первым, а затем имя, и я снова хотел сортировать по первой части имени? После того же формата я бы получил: 'sorted (d.items(), key = lambda (num, name): (num, name.rsplit (None, 1) [0])), но как бы я включил что-то например 'key = operator.itemgetter (1)'? Спасибо – 2013-04-18 07:19:47

+0

Если вы сортируете один и тот же ключ, кортеж должен быть таким же: '(name.rsplit (None, 1) [0], num)'. Изменяется только порядок аргументов лямбды. 'itemgetter' вам не поможет, если вам еще нужно разбить имя. Как ваш инвертированный словарь обрабатывает повторяющиеся номера? –

0

Чтобы просто выкручиваться вы можете сделать это:

sorted_stuff = sorted([(ord(x[0]), x, y) for x, y in d.items()]) 
final_sorted = [(y,z) for x,y,z in sorted_stuff] 

sorted_stuff будет выглядеть следующим образом:

[(77, 'Mary XXIV', 24), (82, 'Robert III', 3)] 

final_sorted будет отформатирован:

[('Mary XXIV', 24), ('Robert III', 3)] 
Смежные вопросы