2013-04-03 31 views
6

Giả sử tôi có từ điển của các vị vua có chữ số La Mã trong tên của họ làm khóa, các chữ số La Mã dưới dạng số nguyên làm giá trị.Python: sắp xếp các mục trong từ điển bằng một phần của khóa?

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}

Tôi muốn sắp xếp danh sách từ cũ nhất đến út, đó là Usamec XLII nên đến trước khi Usamec XLIX. Tôi cũng muốn sắp xếp danh sách theo thứ tự bảng chữ cái, đó là Usamec XLII nên đến trước Zemco III.

cách tiếp cận của tôi là sắp xếp theo tên trước, sau đó theo giá trị chữ số la mã như vậy:

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

Tuy nhiên, do các chữ số La Mã là một phần của khóa, sắp xếp theo bảng chữ cái của tôi không hoạt động như dự kiến. Câu hỏi của tôi là, tôi có thể sắp xếp từ điển bằng một phần của khóa, ví dụ nếu khóa của tôi là Zemco III, tôi có thể sắp xếp các mục của mình bằng cách nào đó bằng key.split() [0] thay vì toàn bộ khóa không? Cảm ơn!

Trả lời

2

key chỉ là một chức năng nhận được một mục và trả về những gì bạn cần sắp xếp. Nó có thể là bất cứ thứ gì.

này sắp xếp các mục theo (name_without_rightmost_word, number) chính:

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)] 

Nếu bạn sử dụng python 3, sử dụng này key:

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

 

key.rsplit(None, 1)[0] là tốt hơn so với key.split()[0] trong trường hợp tên nhiều từ.

+0

Điều này đã hiệu quả. Cảm ơn, Pavel! –

+0

Là câu hỏi tiếp theo, điều gì sẽ xảy ra nếu từ điển của tôi được đặt hàng nên số điện thoại đến trước, rồi tên, và tôi lại muốn sắp xếp theo phần đầu của tên? Theo định dạng tương tự, tôi sẽ nhận được: 'được sắp xếp (d.items(), key = lambda (num, tên): (num, name.rsplit (None, 1) [0]))' nhưng tôi sẽ kết hợp thứ gì đó cũng giống như 'key = operator.itemgetter (1)'? Cảm ơn –

+0

Nếu bạn sắp xếp theo cùng một khóa, bộ dữ liệu phải giống nhau: '(name.rsplit (Không, 1) [0], num)'. Chỉ thứ tự của các đối số 'lambda' thay đổi. 'itemgetter' sẽ không giúp bạn nếu bạn vẫn phải tách tên. Từ điển ngược của bạn xử lý các số trùng lặp như thế nào? –

0

Để chỉ nhận được nó sắp xếp bạn có thể làm điều này:

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] 

Các sorted_stuff sẽ trông như thế này:

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

Các final_sorted sẽ được định dạng đúng cách:

[('Mary XXIV', 24), ('Robert III', 3)] 
Các vấn đề liên quan