My understanding about filtering lists with lambda is that the filter will return all the elements of the list that return True for the lambda function. In that case, for the following code,
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)
The output should be
['4', '5', '6', 'b']
['1', '2', '4', 'c']
['4', '5', '7', 'd']
But the output that I get is
['4', '5', '6', 'b']
['4', '5', '7', 'd']
I get the expected output, if I use
outputlist = filter(lambda x: (x[0] != "1" or x[1] != "2" or x[2] != "3"), inputlist)
What am I doing silly here? Or is my understanding not correct?
Using Loc to Filter With Multiple ConditionsAdd each condition you want to be included in the filtered result and concatenate them with the & operator. You'll see our code sample will return a pd. dataframe of our filtered rows. Don't forget to include "import pandas as pd" at the top!
A lambda function can have as many arguments as you need to use, but the body must be one single expression.
Lambda functions does not allow multiple statements, however, we can create two lambda functions and then call the other lambda function as a parameter to the first function.
x = ['1', '2', '4', 'c']
, so x[1]=='2'
, which makes the expression (x[0] != "1" and x[1] != "2" and x[2] != "3")
be evaluated as False
.
When conditions are joined by and
, they return True
only if all conditions are True
, and if they are joined by or
, they return True
when the first among them is evaluated to be True
.
['1', '2', '4', 'c']
Fails for condition
x[0] != "1"
as well as
x[1] != "2"
Instead of using or
, I believe the more natural and readable way is:
lambda x: (x[0], x[1], x[2]) != ('1','2','3')
Out of curiosity, I compared three methods of, er... comparing, and the results were as expected: slicing lists was the slowest, using tuples was faster, and using boolean operators was the fastest. More precisely, the three approaches compared were
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
And the results, respectively:
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.2399928924012329, 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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With