[Solved] Filter list with complex expression


I believe this does what you want…

arr = [[2,6,8],[1,4,7],[3,3,4],[2,4,9],[3,3,7]]

foo = lambda arr, evenOdd, noDoubles: [ i for i in arr if not (evenOdd and (all(k % 2 == 1 for k in i) or all(k%2 == 0 for k in i))) and not (noDoubles and (len(i) != len(set(i))))]

print(foo(arr, False, False))
print(foo(arr, True, False))
print(foo(arr, False, True))
print(foo(arr, True, True))

 $ python3 foo.py
[[2, 6, 8], [1, 4, 7], [3, 3, 4], [2, 4, 9], [3, 3, 7]]
[[1, 4, 7], [3, 3, 4], [2, 4, 9]]
[[2, 6, 8], [1, 4, 7], [2, 4, 9]]
[[1, 4, 7], [2, 4, 9]]
 $

Let’s break it down a little.

[ i for i in arr if ... ] – You can use list comprehensions to do filtering like this. We just need to make sure that ... evaluates to True or False correctly depending on the element.

not (evenOdd and (all(k % 2 == 1 for k in i) or all(k%2 == 0 for k in i))) – This is the evenOdd test. If evenOdd is False, then the statement will short circuit to True, meaning the element should not be filtered. If evenOdd is True, then all(k % 2 == 1 for k in i) tests if each element of i is odd (and the next test checks for even).

and – If either test fails, the element should be filtered.

not (noDoubles and (len(i) != len(set(i)))) – If noDoubles is False, then the expression short circuits to True. If noDoubles is True, then len(i) != len(set(i))) is just a dirty test for duplicates.

4

solved Filter list with complex expression