2013-04-03 10 views
6

Powiedz, że mam słownik królów z cyframi rzymskimi w ich nazwach jako klucz, cyfry rzymskie w postaci liczby całkowitej jako wartości.Python: sortowanie elementów w słowniku za pomocą części klucza?

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}

Chciałbym, aby posortować listę od najstarszego do najmłodszego, czyli Usamec XLII powinny pochodzić przed Usamec XLIX. Chciałbym również posortować listę alfabetycznie, czyli Usamec XLII powinien nadejść przed Zemco III.

Moje podejście było sortować według nazwy, potem przez roman nominał jako takie:

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

Jednakże, ponieważ cyfry rzymskie są częścią klucza, mój alfabetycznego sortowania nie działa zgodnie z przeznaczeniem. Moje pytanie brzmi: czy mogę posortować słownik według części klucza, na przykład, jeśli mój klucz to Zemco III, czy mogę sortować moje rzeczy w jakiś sposób za pomocą key.split() [0] zamiast całego klucza? Dzięki!

Odpowiedz

2

key to tylko funkcja, która odbiera element i zwraca to, na co trzeba posortować. To może być wszystko.

ta sortuje elementy według klucza (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)] 

Jeśli używasz python 3, użyj tego key:

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

 

key.rsplit(None, 1)[0] jest lepsza niż key.split()[0] w przypadku nazwy wielu przedsiębiorstw.

+0

To działało. Dziękuję, Pavel! –

+0

Jako pytanie uzupełniające, co zrobić, jeśli mój słownik został zamówiony, więc numer był pierwszy, a następnie nazwa, a ja ponownie chciał sortować według pierwszej części nazwy? Podążając za tym samym formatem, otrzymam: 'posortowane (d.items(), key = lambda (num, name): (num, name.rsplit (None, 1) [0]))' ale w jaki sposób mogę włączyć coś podobnie jak 'key = operator.itemgetter (1)' również? Dzięki –

+0

Jeśli sortujesz za pomocą tego samego klucza, krotka powinna być taka sama: '(name.rsplit (None, 1) [0], num)'. Zmienia się tylko kolejność argumentów lambda. 'itemgetter' nie pomoże, jeśli nadal będziesz musiał podzielić nazwę. Jak twój odwrócony słownik będzie obsługiwał duplikaty liczb? –

0

po prostu dostać sortowane można to zrobić:

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 będzie wyglądać następująco:

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

final_sorted zostanie sformatowana poprawnie:

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