Check if an item is in a nested list

in a simple list following check is trivial:

x = [1, 2, 3]

2 in x  -> True

but if it is a list of list, such as:

x = [[1, 2, 3], [2, 3, 4]]

2 in x   -> False

how can this be addressed in order to return True?


Solution 1:

Try this, using the built-in any function. It's the most idiomatic solution, and it's also efficient, because any short-circuits and stops as soon as it finds the first match:

x = [[1, 2, 3], [2, 3, 4]]
any(2 in sl for sl in x)
=> True

Solution 2:

Here's a recursive version that works for any level of nesting.

def in_nested_list(my_list, item):
    """
    Determines if an item is in my_list, even if nested in a lower-level list.
    """
    if item in my_list:
        return True
    else:
        return any(in_nested_list(sublist, item) for sublist in my_list if isinstance(sublist, list))

Here are a few tests:

x = [1, 3, [1, 2, 3], [2, 3, 4], [3, 4, [], [2, 3, 'a']]]
print in_nested_list(x, 2)
print in_nested_list(x, 5)
print in_nested_list(x, 'a')
print in_nested_list(x, 'b')
print in_nested_list(x, [])
print in_nested_list(x, [1, 2])
print in_nested_list(x, [1, 2, 3])

True
False
True
False
True
False
True

Solution 3:

You can use set.issubset() and itertools.chain():

In [55]: x = [[1, 2, 3], [2, 3, 4]]

In [56]: {4}.issubset(chain.from_iterable(x))
Out[56]: True

In [57]: {10}.issubset(chain.from_iterable(x))
Out[57]: False

You can also chek the membership for multiple items efficiently:

In [70]: {2, 4}.issubset(chain.from_iterable(x))
Out[70]: True

In [71]: {2, 4, 10}.issubset(chain.from_iterable(x))
Out[71]: False

Solution 4:

This would work:

for arr in x:
    if 2 in arr:
        print True
        break

I would recommend Oscar's answer as any is the right option here.