2016-07-14 14 views
2

Mein Verständnis über das Filtern von Listen mit Lambda ist, dass der Filter alle Elemente der Liste zurückgibt, die True für die Lambda-Funktion zurückgeben. In diesem Fall für den folgenden Code,Python Lambda-Liste Filterung mit mehreren Bedingungen

inputlist = [] 
inputlist.append(["1", "2", "3", "a"]) 
inputlist.append(["4", "5", "6", "b"]) 
inputlist.append(["1", "2", "4", "c"]) 
inputlist.append(["4", "5", "7", "d"]) 

outputlist = filter(lambda x: (x[0] != "1" and x[1] != "2" and x[2] != "3"), inputlist) 
for item in outputlist: print(item) 

sollte die Ausgabe

['4', '5', '6', 'b'] 
['1', '2', '4', 'c'] 
['4', '5', '7', 'd'] 

sein, aber die Ausgabe, die ich erhalte, ist

['4', '5', '6', 'b'] 
['4', '5', '7', 'd'] 

ich die erwartete Ausgabe zu bekommen, wenn ich

outputlist = filter(lambda x: (x[0] != "1" or x[1] != "2" or x[2] != "3"), inputlist) 

Was bin ich doi Dumm hier? Oder ist mein Verständnis nicht korrekt?

+0

Wir können nicht sagen, ob Ihr Verständnis richtig ist, weil Sie uns nicht gesagt haben, was Sie erwarten, die 'Lambda'-Funktion zu tun. Wenn Sie die Bedingungen mit "und" verknüpfen, wird es nicht zu "wahr" ausgewertet, solange nicht alle Bedingungen erfüllt sind. Wenn Sie die Bedingungen mit "oder" verknüpfen, wird "wahr" ausgewertet, wenn nur eine der Bedingungen zutrifft. –

+0

Jetzt fühle ich mich wirklich dumm! Ich denke, ich muss aufhören zu arbeiten und in den Sack fallen. Entschuldigung, dass du deine Zeit verschwendet hast. – user3300676

Antwort

4

x = ['1', '2', '4', 'c'], also x[1]=='2', was den Ausdruck (x[0] != "1" and x[1] != "2" and x[2] != "3") als False auswerten lässt.

Wenn die Bedingungen von and verbunden sind, kehren sie True nur, wenn alle Bedingungen True sind, und wenn sie von or verbunden sind, kehren sie True, wenn der erste unter ihnen ausgewertet True zu sein.

2

Nun, ['1', '2', '4', 'c'] erfüllt nicht die Bedingung, dass x[0] != "1", noch erfüllt es die Bedingung x[1] != "2".

3
['1', '2', '4', 'c'] 

schlägt für Zustand

x[0] != "1" 

sowie

x[1] != "2" 

Statt or zu verwenden, glaube ich, die natürlichere und lesbare Weise ist:

lambda x: (x[0], x[1], x[2]) != ('1','2','3') 

Out von Neugier, Ich verglich drei Methoden zum Vergleichen und die Ergebnisse waren wie erwartet: Slicing-Listen waren die langsamsten, die Verwendung von Tupeln war schneller und die Verwendung boolescher Operatoren war am schnellsten. Genauer gesagt, im Vergleich die drei Ansätze waren

list_slice_compare = lambda x: x[:3] != [1,2,3] 

tuple_compare = lambda x: (x[0],x[1],x[2]) != (1,2,3) 

bool_op_compare = lambda x: x[0]!= 1 or x[1] != 2 or x[2]!= 3 

Und die Ergebnisse, jeweils:

In [30]: timeit.Timer(setup="import timeit,random; rand_list = [random.randint(1,9) for _ in range(4)]; list_slice_compare = lambda x: x[:3] != [1,2,3]", stmt="list_slice_compare(rand_list)").repeat() 
Out[30]: [0.3207617177499742, 0.3230015148823213, 0.31987868894918847] 

In [31]: timeit.Timer(setup="import timeit,random; rand_list = [random.randint(1,9) for _ in range(4)]; tuple_compare = lambda x: (x[0],x[1],x[2]) != (1,2,3)", stmt="tuple_compare(rand_list)").repeat() 
Out[31]: [0.2399928924, 0.23692036176475995, 0.2369164465619633] 

In [32]: timeit.Timer(setup="import timeit,random; rand_list = [random.randint(1,9) for _ in range(4)]; bool_op_compare = lambda x: x[0]!= 1 or x[1] != 2 or x[2]!= 3", stmt="bool_op_compare(rand_list)").repeat() 
Out[32]: [0.144389363900018, 0.1452672728203197, 0.1431527621755322] 
+1

Wenn Sie eine Liste auf der rechten Seite des '! =' Verwenden, können Sie dann eine Scheibe auf der linken Seite verwenden: x [: 3]! = ["1", "2", "3"] ' – Blckknght

+0

@Blckknght Wahr. –

2

Der Filter genau handelt, wie es sollte. Im ersten Fall

lambda x: (x[0] != "1" and x[1] != "2" and x[2] != "3") 

der Filter nur „akzeptiert“ Listen, deren erstes Element nicht 1 ist und das zweite Element, dessen nicht 2 und dessen dritte Element ist nicht 3. Somit ist die Liste ['1', '2', '4', 'c'] wird es nicht, weil ihr machen durch erstes Element 1. im Gegenteil,

lambda x: (x[0] != "1" or x[1] != "2" or x[2] != "3") 

jede Liste erstes Element, das nicht akzeptieren ist, das 1 oder zweites Element nicht 2 ist, oder deren dritte Element ist nicht mehr als 3.So wird ['1', '2', '4', 'c'] akzeptiert, weil sein drittes Element nicht 3.