2015-05-12 15 views
10

Tôi có một danh sách phẳng các đối tượng duy nhất, một số trong đó có thể chia sẻ một thuộc tính nhất định với những đối tượng khác. Tôi muốn tạo danh sách liệt kê lồng nhau, với các đối tượng được nhóm theo thuộc tính đã cho. Như một ví dụ nhỏ, đưa ra danh sách sau đây:Giữ một danh sách phẳng dựa trên tiêu chí tùy ý

>>> flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"] 

tôi có thể muốn để nhóm nó theo chiều dài, ví dụ:

>>> nest_by_length(flat) 
[['tie', 'hat'], ['shoes', 'pants', 'shirt'], ['jacket']] 

Tôi đã nhìn thấy một vài similarquestionssuggestions. Tuy nhiên, trong tất cả các trường hợp này, lồng nhau được dựa trên thứ tự của danh sách đầu vào. Trong trường hợp của tôi, thứ tự của danh sách đầu vào là hoàn toàn không thể đoán trước, cũng như số lượng các danh sách con cho đầu ra và số lượng các mục cho mỗi danh sách con.

Có chức năng tiêu chuẩn hoặc cách thành ngữ để thực hiện việc này không?

Trả lời

10

Một thành ngữ phổ biến đối với một danh sách hiện là sử dụng groupby trong itertools:

from itertools import groupby 

flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"] 

result=[] 
for k, g in groupby(sorted(flat, key=len), key=len): 
    result.append(list(g)) 

print result 

Hoặc, ngắn gọn hơn:

[list(g) for _,g in groupby(sorted(flat, key=len), key=len)] 

Prints:

[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']] 

Input để groupby được được nhóm thành các nhóm dựa trên giá trị thay đổi của đầu ra của hàm quan trọng, trong trường hợp này len. Nói chung, bạn cần đặt trước danh sách dựa trên cùng một chức năng chính, do đó, chức năng sorted được gọi trước tiên.

Nếu danh sách nguồn của bạn không hoàn thành được nêu, hoặc không thể sắp xếp dựa trên tiêu chuẩn (hoặc bạn sẽ chỉ thích tùy chọn khác), tạo ra một dict mà các bản đồ tiêu chí của bạn đến một giá trị khóa duy nhất:

groups={} 
for e in flat: 
    groups.setdefault(len(e), []).append(e) 

print groups  
# {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']} 

bạn cũng có thể sử dụng defaultdict hơn setdefault với giá trị key tùy ý:

from collections import defaultdict 
groups=defaultdict(list) 
for e in flat: 
    groups[len(e)].append(e) 
# groups=defaultdict(<type 'list'>, {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']}) 

Trong cả hai trường hợp, sau đó bạn có thể tạo danh sách lồng nhau từ đó:

>>> [groups[k] for k in sorted(groups.keys())] 
[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']] 
+0

Tôi đánh giá cao sự thông suốt của bạn. Tôi nghi ngờ sẽ có một số chức năng như groupby mà tôi không biết, nhưng thủ thuật từ điển chỉ là thông minh. Cảm ơn! – Joe

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