2015-07-26 12 views
12

là đầu vào "bẩn" danh sách trong pythonPython - danh sách hiểu trong trường hợp này là hiệu quả?

input_list = [' \n ',' data1\n ',' data2\n',' \n','data3\n'.....] 

mỗi phần tử danh sách chứa một trong hai khoảng trống với ký tự dòng mới hoặc dữ liệu với ký tự xuống dòng

sạch nó lên bằng cách sử dụng mã dưới đây ..

cleaned_up_list = [data.strip() for data in input_list if data.strip()] 

cho

cleaned_up_list = ['data1','data2','data3','data4'..] 

Liệu python trong nội bộ có gọi strip() hai lần trong quá trình đọc danh sách trên không? hoặc tôi sẽ phải sử dụng một vòng lặp lặp lại forstrip() chỉ một lần nếu tôi quan tâm đến hiệu quả?

for data in input_list 
    clean_data = data.strip() 
    if(clean_data): 
     cleaned_up_list.append(clean_data) 
+4

Bạn có thể tự mình tìm ra điều này bằng cách viết hàm tùy chỉnh tăng số lượt truy cập và/hoặc in ra mỗi khi được gọi. –

Trả lời

14

Sử dụng danh sách của bạn comp dải gọi hai lần, sử dụng một exp gen nếu bạn chỉ muốn dải gọi một lần và giữ cho sự hiểu biết:

input_list[:] = [x for x in (s.strip() for s in input_list) if x] 

Input:

input_list = [' \n ',' data1\n ',' data2\n',' \n','data3\n'] 

Đầu ra:

['data1', 'data2', 'data3'] 

input_list[:] sẽ thay đổi danh sách ban đầu có thể hoặc không thể là thứ bạn muốn, nếu bạn thực sự muốn tạo danh sách mới chỉ cần sử dụng cleaned_up_list = ....

tôi luôn luôn tìm thấy bằng itertools.imap trong python 2 và map trong python 3 thay vì các máy phát điện là hiệu quả nhất cho đầu vào lớn hơn:

from itertools import imap 
input_list[:] = [x for x in imap(str.strip, input_list) if x] 

Một số timings với cách tiếp cận khác nhau:

In [17]: input_list = [choice(input_list) for _ in range(1000000)] 

In [19]: timeit filter(None, imap(str.strip, input_list)) 
10 loops, best of 3: 115 ms per loop 

In [20]: timeit list(ifilter(None,imap(str.strip,input_list))) 
10 loops, best of 3: 110 ms per loop 

In [21]: timeit [x for x in imap(str.strip,input_list) if x] 
10 loops, best of 3: 125 ms per loop 

In [22]: timeit [x for x in (s.strip() for s in input_list) if x] 
10 loops, best of 3: 145 ms per loop 

In [23]: timeit [data.strip() for data in input_list if data.strip()] 
10 loops, best of 3: 160 ms per loop 

In [24]: %%timeit             
    ....:  cleaned_up_list = [] 
    ....:  for data in input_list: 
    ....:   clean_data = data.strip() 
    ....:   if clean_data: 
    ....:    cleaned_up_list.append(clean_data) 
    ....: 

10 loops, best of 3: 150 ms per loop 

In [25]: 

In [25]: %%timeit              
    ....:  cleaned_up_list = [] 
    ....:  append = cleaned_up_list.append 
    ....:  for data in input_list: 
    ....:   clean_data = data.strip() 
    ....:   if clean_data: 
    ....:    append(clean_data) 
    ....: 

10 loops, best of 3: 123 ms per loop 

Cách tiếp cận nhanh nhất thực tế là itertools.ifilter kết hợp với itertools.imap theo sau là filter với imap.

Xóa nhu cầu đánh giá lại tham chiếu hàm list.append mỗi lần lặp lại hiệu quả hơn, nếu bạn bị mắc kẹt với vòng lặp và muốn phương pháp hiệu quả nhất thì đó là một giải pháp khả thi.

+1

Nó nhẹ hơn gọi 'dải()' hai lần? – clemtoy

+1

Đối với rất nhiều dữ liệu, có, bởi vì bạn thiết lập hiểu một lần, nhưng dải được gọi trên mọi phần tử trong danh sách. –

+0

@clemtoy, tôi đã thêm một số thời gian cho các cách tiếp cận khác nhau, bạn có thể thấy rằng dải gọi hai lần là cách tiếp cận hiệu quả nhất –

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