tenac
tenac

Reputation: 97

Filtering nested list

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']]

Upvotes: 8

Views: 11407

Answers (8)

MoeObeidat
MoeObeidat

Reputation: 21

this is pretty close to what you have

    the_list = [['blue'], ['blue', 'red', 'black'], ['green', 'yellow'], 
    ['yellow', 'green'], ['orange'], ['white', 'gray']]
    filters = ['blue', 'white']

    filtered_list = []

    for sublist in the_list:
        sub_filtered_list=[]
        for item in sublist:
           if item in filters:
                continue
            else:
                sub_filtered_list.extend([item])
        if sub_filtered_list==[]:
            continue
        else:
            filtered_list.append(sub_filtered_list)

    print(filtered_list)

Upvotes: 2

wwii
wwii

Reputation: 23753

Using sets.

the_list = map(set, the_list)
filters = set(filters)

fl = []
for sub in the_list:
    sub = sub.difference(filters)
    if sub:
        fl.append(list(sub))

Upvotes: 3

Prasanta Bose
Prasanta Bose

Reputation: 674

filtered_list=[];
for sublist in the_list:
    if len(list(set(sublist).intersection(filters_exclude)))>0:
        break;
    filtered_list.append(sublist);

set(sublist).intersection(filters_exclude) returns the intersection of both the lists. List() converts the set into List. Len() returns the length of the List.

Upvotes: 1

RoadRunner
RoadRunner

Reputation: 26315

You can also filter() out lists that don't have an intersection with the list filters, using Set intersection:

>>> the_list = [['blue'], ['blue', 'red', 'black'], ['green', 'yellow'], ['yellow', 'green'], ['orange'], ['white', 'gray']]
>>> filters = ['blue', 'white']
>>> list(filter(lambda x: not set(x).intersection(filters), the_list))
[['green', 'yellow'], ['yellow', 'green'], ['orange']]

Or with a comprehension:

>>> [x for x in the_list if not set(x).intersection(filters)]
[['green', 'yellow'], ['yellow', 'green'], ['orange']]

Upvotes: 3

Ajax1234
Ajax1234

Reputation: 71451

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)

Upvotes: 4

Alexander
Alexander

Reputation: 109546

You can use a conditional list comprehension.

>>> [sublist for sublist in the_list 
     if all(filter not in set(sublist) for filter in filters)]
[['green', 'yellow'], ['orange']]

Upvotes: 3

AetherUnbound
AetherUnbound

Reputation: 1744

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]]

Upvotes: 3

sytech
sytech

Reputation: 40941

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.

Upvotes: 5

Related Questions