2015-07-26 18 views
12

Das ist der Eingang „dirty“ -Liste in PythonPython - Listenverständnis in diesem Fall ist effizient?

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

jedes Listenelement entweder leere Räume mit neuen Zeilen Zeichen oder Daten mit Neuem-Zeile-Zeichen

den folgenden Code Gereinigte enthält bis ..

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

gibt

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

Ruft Python intern während des obigen Listenverständnisses intern strip() auf? oder würde ich eine for Schleife Iteration und strip() nur einmal verwenden müssen, wenn ich mich um Effizienz kümmerte?

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

Sie können dies selbst herausfinden, indem Sie eine benutzerdefinierte Funktion schreiben, die einen Zähler erhöht und/oder bei jedem Aufruf ausdruckt. –

Antwort

14

Mit Ihrer Liste comp Streifen ist zweimal genannt, ein Gen exp verwenden, wenn Sie einmal nur Anruf Streifen wollen und halten das Verständnis:

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

Eingang:

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

Ausgang:

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

input_list[:] wird die ursprüngliche Liste ändern, die möglicherweise nicht das ist, was Sie wollen, wenn Sie tatsächlich eine neue Liste erstellen möchten, verwenden Sie einfach cleaned_up_list = ....

I für größere Eingänge mit itertools.imap in Python 2 und map in Python 3 anstelle des Generators am effizientesten sein immer gefunden:

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

Einige Timings mit unterschiedlichen Ansätzen:

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 

Der schnellste Ansatz ist tatsächlich itertools.ifilter kombiniert mit itertools.imap dicht gefolgt von filter mit imap.

Die Notwendigkeit, die Funktionsreferenz list.append neu zu bewerten, ist effizienter, wenn Sie mit einer Schleife stecken bleiben und den effizientesten Ansatz suchen, dann ist dies eine praktikable Alternative.

+1

Ist es leichter als zweimal 'strip()' aufzurufen? – clemtoy

+1

Für viele Daten, ja, weil Sie die Comprehensions einmal eingerichtet haben, aber der Strip wird für jedes Element in der Liste aufgerufen. –

+0

@clemtoy, habe ich einige Timings für verschiedene Ansätze hinzugefügt, können Sie sehen, dass Calling Strip zweimal der am wenigsten effiziente Ansatz ist –

Verwandte Themen