2009-09-28 28 views
5

Howdy, codeboys và codegirls!Đánh giá vào hai hoặc nhiều danh sách

Tôi đã gặp một vấn đề đơn giản với giải pháp có vẻ dễ dàng. Nhưng là một người phi thường Python, tôi cảm thấy rằng có một cách tiếp cận tốt hơn ở đâu đó.

Giả sử bạn có danh sách các chuỗi hỗn hợp. Có hai loại chuỗi cơ bản trong bao - những cái có "=" trong chúng (a = khoai tây) và những chuỗi không có (Lady Jane). Những gì bạn cần là sắp xếp chúng thành hai danh sách.

Cách tiếp cận rõ ràng là:

for arg in arguments: 
    if '=' in arg: 
     equal.append(arg) 
    else: 
     plain.append(arg) 

Có bất kỳ khác, cách thanh lịch hơn vào nó? Một cái gì đó như:

equal = [arg for arg in arguments if '=' in arg] 

nhưng để sắp xếp thành nhiều danh sách?

Và điều gì sẽ xảy ra nếu bạn có nhiều loại dữ liệu?

+3

Tôi nghĩ rằng cách tiếp cận rõ ràng của bạn là hoàn toàn tốt và dễ đọc hơn nhiều câu trả lời đề xuất cho đến nay! –

+0

Thật vậy, tôi thấy danh sách hiểu là một trong những tính năng thanh lịch nhất của python mà tôi liên tục thèm khi viết C++! 2 trong số đó là đẹp hơn nhiều so với bất kỳ câu trả lời – Steg

Trả lời

4

Hãy thử

for arg in arguments: 
    lst = equal if '=' in arg else plain 
    lst.append(arg) 

hoặc (thánh xấu xí)

for arg in arguments: 
    (equal if '=' in arg else plain).append(arg) 

Một lựa chọn thứ ba: Tạo một lớp mà cung cấp append() và đó phân loại thành nhiều danh sách.

+0

Tôi tìm thấy dễ đọc hơn các hình thức 'list = ('=' trong arg) và bằng hoặc đồng bằng'. – giorgian

+0

bạn đang shadowing được xây dựng trong – SilentGhost

+0

Tôi nghĩ rằng "a nếu cond else b" là rất dễ đọc tiếng Anh; Tôi chỉ không thích đặt quá nhiều vào một dòng. –

4

Bạn có thể sử dụng itertools.groupby() cho việc này:

import itertools 
f = lambda x: '=' in x 
groups = itertools.groupby(sorted(data, key=f), key=f) 
for k, g in groups: 
    print k, list(g) 
+3

Tôi nghĩ rằng ông yêu cầu cho thanh lịch – Steg

+0

Việc phân loại làm cho nó nlog (n) trong khi một giải pháp đơn giản O (n) tồn tại. –

1

phương pháp khác là sử dụng các filter chức năng, mặc dù nó không phải là giải pháp hiệu quả nhất.
Ví dụ:

>>> l = ['a=s','aa','bb','=', 'a+b'] 
>>> l2 = filter(lambda s: '=' in s, l) 
>>> l3 = filter(lambda s: '+' in s, l) 
>>> l2 
['a=s', '='] 
>>> l3 
['a+b'] 
2
def which_list(s): 
    if "=" in s: 
     return 1 
    return 0 

lists = [[], []] 

for arg in arguments: 
    lists[which_list(arg)].append(arg) 

plain, equal = lists 

Nếu bạn có thêm các loại dữ liệu, thêm một điều khoản nếu để which_list, và khởi lists vào danh sách rỗng hơn.

+0

which_list có thể đơn giản hơn nhiều - xem câu trả lời của tôi. Nếu không, câu trả lời của chúng tôi là khá gần. – PaulMcG

+0

Thật vậy, nó có thể được, nhưng OP hỏi về trường hợp của nhiều hơn hai khả năng, mà tôi muốn đối phó với trong thiết kế ban đầu. –

+0

Trong trường hợp đó, tôi nghĩ từ điển của danh sách sẽ rõ ràng hơn. Các chỉ mục danh sách là vô nghĩa. –

3

Tôi sẽ chỉ đọc hai danh sách. Trong khi đó có một số chi phí phát sinh (hai vòng trong danh sách), nó là nhiều Pythonic để sử dụng một danh sách hiểu hơn để sử dụng cho. Nó cũng là (trong tâm trí của tôi) dễ đọc hơn nhiều so với sử dụng tất cả các loại thủ thuật thực sự mát mẻ, nhưng ít người biết về.

1

Tôi đặt nó lại với nhau, và sau đó thấy rằng Ned Batchelder đã có trên cùng một tack. Tôi đã chọn để gói các phương pháp tách thay vì chọn danh sách, mặc dù, và chỉ sử dụng các giá trị 0/1 tiềm ẩn cho Sai và True.

def split_on_condition(source, condition): 
    ret = [],[] 
    for s in source: 
     ret[condition(s)].append(s) 
    return ret 

src = "z=1;q=2;lady jane;y=a;lucy in the sky".split(';') 

plain,equal = split_on_condition(src, lambda s:'=' in s) 
1

Cách tiếp cận của bạn là tốt nhất. Để phân loại thành hai danh sách, nó không thể rõ ràng hơn. Nếu bạn muốn nó là một lớp lót, hãy gói gọn nó trong một hàm:

def classify(arguments): 
    equal, plain = [], [] 
    for arg in arguments: 
     if '=' in arg: 
      equal.append(arg) 
     else: 
      plain.append(arg) 
    return equal, plain 


equal, plain = classify(lst) 
2

Tôi sẽ tìm cách tiếp cận của Edan, ví dụ:

equal = [arg for arg in arguments if '=' in arg] 
plain = [arg for arg in arguments if '=' not in arg] 
2

Tôi đọc ở đâu đây mà bạn có thể quan tâm đến một giải pháp mà sẽ làm việc cho hơn hơn hai định danh (dấu bằng và không gian).

Giải pháp sau đây yêu cầu bạn cập nhật uniques được đặt bằng bất kỳ điều gì bạn muốn khớp, kết quả được đặt trong từ điển danh sách với số nhận dạng làm khóa.

uniques = set('= ') 
matches = dict((key, []) for key in uniques) 

for arg in args: 
    key = set(arg) & uniques 
    try: 
     matches[key.pop()].append(arg) 
    except KeyError: 
     # code to handle where arg does not contain = or ' '. 

Bây giờ mã trên giả định rằng bạn sẽ chỉ có một trận đấu duy nhất cho nhận dạng của bạn trong arg của bạn. Nghĩa là bạn không có arg trông giống như thế này 'John= equalspace'. Bạn cũng sẽ phải suy nghĩ về cách bạn muốn đối xử với trường hợp không khớp với bất kỳ thứ gì trong tập hợp (KeyError xảy ra.)

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