2009-08-01 80 views
28

Vẫn còn học python (cuối cùng!) Và không thể hoàn toàn quấn quanh đầu của tôi được nêu ra. Những gì tôi muốn làm là sắp xếp một từ điển của danh sách theo giá trị bằng cách sử dụng mục thứ ba trong danh sách. Thật dễ dàng khi sắp xếp một từ điển theo giá trị khi giá trị chỉ là một số hoặc một chuỗi, nhưng điều danh sách này làm tôi bối rối.Python: sắp xếp một từ điển của danh sách

Ví dụ:

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

Tôi muốn để có thể lặp qua hết từ điển theo thứ tự giá trị thứ ba trong mỗi danh sách, trong trường hợp này 9, 3, 11.

Cảm ơn nhiều cho bất kỳ Cứu giúp!

Trả lời

33

Dưới đây là một cách để làm điều này:

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

Các key argument của sorted chức năng cho phép bạn lấy được một chìa khóa sắp xếp cho mỗi phần tử của danh sách.

Để lặp qua các phím/giá trị trong danh sách này, bạn có thể sử dụng một cái gì đó như:

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

Ngay sau khi tôi hỏi câu hỏi tôi đã có một hiển linh và về cơ bản đã đưa ra cùng một điều ngoại trừ lambda (chưa biết về chúng). Chỉ cần viết chức năng cmp của riêng tôi có trong tupples từ dict.items() và trả về kết quả. Điều tương tự, chỉ là một cách khác để viết nó. Cảm ơn nhiều vì đã trả lời nhanh! – jay

+0

Giải pháp tuyệt vời. Tôi yêu sự đơn giản của 'được sắp xếp()'. –

+4

Tôi nghĩ rằng nó là một chút rõ ràng hơn theo cách này: sắp xếp (myDict.items(), key = lambda (k, v): v [2]) –

2

Bạn nói hai khá khác nhau muốn:

  1. "Những gì tôi muốn làm là loại một từ điển của danh sách ... "
  2. " Tôi muốn có thể lặp qua từ điển theo thứ tự ... "

Việc đầu tiên trong số đó là theo định nghĩa không thể - để sắp xếp một cái gì đó ngụ ý sắp xếp lại theo một trật tự nào đó. Các từ điển Python vốn không có thứ tự. Thứ hai sẽ mơ hồ có thể nhưng rất khó được thực hiện.

Những gì bạn có thể làm là

  1. Hãy sao chép các nội dung từ điển (mà sẽ được khá có thứ tự)
  2. Sắp xếp mà
  3. lặp qua các kết quả được sắp xếp - và bạn đã có hai giải pháp cho điều đó. Nhân tiện, giải pháp sử dụng "khóa" thay vì của "cmp" thì tốt hơn; xem sorted

"mục thứ ba trong danh sách" có mùi như "món thứ ba trong tuple" với tôi và "e [1] [2]" chỉ có mùi :-) ... bạn có thể thích để điều tra sử dụng các bộ dữ liệu có tên thay vì danh sách; thấy named tuple factory

Nếu bạn đang đi để được làm trích lục/sắp xếp/quá trình thường xuyên trên các tập dữ liệu lớn, bạn có thể muốn xem xét một cái gì đó như thế này, bằng cách sử dụng mô-đun sqlite3 Python-cung cấp:

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

Như John Machlin nói rằng bạn không thể thực sự sắp xếp một từ điển Python.

Tuy nhiên, bạn có thể tạo chỉ mục các khóa có thể được sắp xếp theo bất kỳ thứ tự nào bạn muốn.

Mẫu Python ưa thích (thành ngữ) để sắp xếp theo bất kỳ tiêu chí thay thế nào được gọi là "trang trí-sắp xếp-undecorate" (DSU). Trong thành ngữ này, bạn tạo một danh sách tạm thời chứa các bộ dữ liệu chính của bạn, sau đó gọi các phần tử dữ liệu gốc của bạn, sau đó gọi phương thức .sort() trên danh sách đó (hoặc, trong các phiên bản gần đây của Python trang trí trong một được gọi là được sắp xếp() chức năng tích hợp sẵn). Sau đó, bạn xóa "đồ trang trí".

Lý do thường được ưu tiên hơn so với chức năng so sánh truyền sang phương thức .sort() là mã phân loại mặc định được tích hợp sẵn của Python (được biên dịch C trong C Python bình thường) rất nhanh và hiệu quả trong trường hợp mặc định , nhưng nhiều, chậm hơn nhiều khi nó phải gọi mã đối tượng Python nhiều, nhiều lần trong trường hợp không mặc định. Vì vậy, nó thường tốt hơn nhiều để lặp qua dữ liệu tạo cấu trúc dữ liệu mà có thể được chuyển đến các thói quen sắp xếp mặc định.

Trong trường hợp này bạn sẽ có thể sử dụng một cái gì đó như:

[y[1] for y in sorted([(myDict[x][2], x) for x in myDict.keys()])] 

... đó là một sự hiểu biết danh sách làm undecorate từ danh sách được sắp xếp của các bộ hiện đang được trả về bởi danh sách hiểu bên trong. Hiểu bên trong là tạo tập hợp các bộ dữ liệu, khóa phân loại mong muốn của bạn (phần tử thứ 3 của danh sách) và khóa của từ điển tương ứng với khóa sắp xếp. myDict.keys() là, tất nhiên, một phương thức từ điển Python trả về một danh sách tất cả các khóa hợp lệ theo thứ tự bất kỳ mà triển khai cơ bản chọn --- có lẽ là một phép lặp đơn giản trên các băm.

Một cách tiết hơn để làm điều này có thể được dễ dàng hơn để đọc:

temp = list() 
for k, v in myDict.items(): 
    temp.append((v[2],)) 
temp.sort() 
results = list() 
for i in temp: 
    results.append(i[1]) 

Thông thường, bạn nên xây dựng mã như vậy lặp đi lặp lại, trong phiên dịch sử dụng các mẫu dữ liệu nhỏ. Xây dựng biểu thức hoặc chức năng "trang trí". Sau đó, bọc trong cuộc gọi tới được sắp xếp(). Sau đó, xây dựng biểu thức undecorate (thường đơn giản như những gì tôi đã hiển thị ở đây).

+0

(1) Bạn so sánh trang trí-sắp xếp-undecorate bằng cách sử dụng cmp arg; giới thiệu khóa arg cắt nhỏ một phần rất lớn của lãnh thổ DSU. (2) Giải pháp của bạn rời khỏi OP với một danh sách các phím dict ... để có được những gì ông muốn, ông sẽ phải làm thêm một vòng lặp của các mục dict (3) cách tiết của bạn có một typo: s/v [2],/v [2], k / –

Các vấn đề liên quan