I want to filter a nested list by another list which can be of variable length. If any item of a sublist matches any element of the filter list, the sublist should be excluded. The following code works for me but is there a "cleaner" solution for this task?
the_list = [['blue'], ['blue', 'red', 'black'], ['green', 'yellow'], ['yellow', 'green'], ['orange'], ['white', 'gray']]
filters = ['blue', 'white']
filtered_list = []
for sublist in the_list:
for item in sublist:
if item in filters:
break
filtered_list.append(sublist)
break
Expected output:
filtered_list = [['green', 'yellow'], ['yellow', 'green'], ['orange']]
Perhaps a bit more semantic would be to use any
.
for sublist in the_list:
if any(item in filters_exclude for item in sublist):
continue
filtered_list.append(sublist)
Maybe overkill, but you could even factor that into its own function then use the builtin filter
def good_list(some_list):
return not any(item in filters_exclude for item in some_list)
filtered_list = filter(good_list, the_list)
This should accomplish the goal you described. However, the code you wrote has potential issues, as mentioend in the comments.
You can use list comprehension:
the_list = [['blue'], ['blue', 'red', 'black'], ['green', 'yellow'],['orange'], ['white', 'gray']]
filters = ['blue', 'white']
final_l = [i for i in the_list if not any(b in filters for b in i)]
Output:
[['green', 'yellow'], ['orange']]
Or, using filter:
final_l = filter(lambda x:not any(b in filters for b in x), the_list)
You can use filter
and map
to make this a "one-liner". It doesn't improve readability, but it works:
filters_exclude = [2, 4]
initial_list = [[1, 2, 3, 4], [1, 2, 3], [2, 3, 4, 5]]
final = list(map(lambda x: filter(lambda y: y not in filters_exclude, x), initial_list)
Example:
>>> filters_exclude = [2, 4]
>>> map(lambda x: filter(lambda y: y not in filters_exclude, x), [[1, 2, 3, 4], [1, 2, 3]])
[[1, 3], [1, 3]]
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