1

I have a list of lists of lists:

lst = [[[1,2,3],[3,4,5]],[1,[2,34,5,[45,67]]]]

I want to check if a value, for example 67, exists inside the list. I have already looked at the StackOverflow question:

How do I check if a list of lists exists in a list of lists?

But it only shows a method of checking if a value is in a list of lists.

How would I search a list, no matter how deep the list is?

  • Does this answer your question? [python: flatten list of lists OF LISTS](https://stackoverflow.com/questions/62335161/python-flatten-list-of-lists-of-lists) – Ewran Apr 15 '21 at 04:38

4 Answers4

2

if your list is not big and you want simple solution then you can convert list to string and check string value of number in that string see below example:

lst = [[[1,2,3],[3,4,5]],[1,[2,34,5,[45,67]]]]
lst1 = str(lst)
print(lst)
print(str(67) in lst1)

output is:

[[[1, 2, 3], [3, 4, 5]], [1, [2, 34, 5, [45, 67]]]]
True
Amit Nanaware
  • 3,203
  • 1
  • 6
  • 19
0

Recursively.

from typing import List, Tuple, Any, Union

RecursiveList = Union[List['RecursiveList'], Any]

def multiindex(lst: List[RecursiveList], item) -> Tuple[int]:
    for idx, elem in enumerate(lst):
        if elem == item:
            return (idx,)
        else:
            # try to call it recursively. 
            # if the current element isn't iterable, enumerate() will throw a TypeError
            # which we can just ignore
            try:
                return (idx,) + multiindex(elem, item)
            except (TypeError, ValueError):
                continue
    raise ValueError(f'{item} is not in list')

l = [[[1,2,3],[3,4,5]],[1,[2,34,5,[45,67]]]]
print(multiindex(l, 67))
# (1, 1, 3, 1)

We can test for containment by simply checking if we get a ValueError searching for it, same as we would with the normal list.index(). Alternatively, just modify the method to return a boolean instead of throwing a ValueError:

def multicontains(lst: List[RecursiveList], item) -> bool:
    for idx, elem in enumerate(lst):
        if elem == item:
            return True
        else:
            try:
                sublist_contains = multicontains(elem, item)
                if sublist_contains:
                    return True
            except TypeError:
                continue
    return False
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • I get 'Traceback (most recent call last): File "./prog.py", line 3, in NameError: name 'Union' is not defined' when I run this. – sasindumaheepala Apr 15 '21 at 07:44
  • @sasindumaheepala sorry, forgot to import `Union` from typing. Fixed. You can remove the annotations if you need to, they're just there for clarity. – Green Cloak Guy Apr 15 '21 at 14:00
0

Apart from converting the list to a string, you can searched for the item in a flatten list.

To get flatten the list, we can use Iterable class from collections.abc.

from collections.abc import Iterable


def get_flatten(ar):
  if isinstance(ar, Iterable):
    return [inner_iterable for i in ar for inner_iterable in get_flatten(i)]
  return [ar]

def get_searched_result(ar, item):
  return item in get_flatten(ar)


if __name__ == "__main__":
  lst = [[[1,2,3],[3,4,5]],[1,[2,34,5,[45,67]]]]
  item = 67
  print(f"{item} in {lst}: {get_searched_result(lst, item)}")


  item = 32
  print(f"{item} in {lst}: {get_searched_result(lst, item)}")

Output:

67 in [[[1, 2, 3], [3, 4, 5]], [1, [2, 34, 5, [45, 67]]]]: True
32 in [[[1, 2, 3], [3, 4, 5]], [1, [2, 34, 5, [45, 67]]]]: False

References:

arshovon
  • 13,270
  • 9
  • 51
  • 69
0

Another recursive way without any library for a nested list. It returns as soon as the value is found.

def find_nested(lst, val):
  if val in lst:
    return True
  for e in lst:
    if e.__class__ == list and find_nested(e, val):
      return True
  return False

So, for example:

lst = [[[1,2,3],[3,4,5]],[1,[2,34,5,[45,67]]],1]

find_nested(lst, 1) #=> True --- it returns at first call
find_nested(lst, 67) #=> True
find_nested(lst, 670) #=> False

find_nested(lst, [3,4,5]) #=> True

You can edit the method so it returns also the list where the value is found. Or let it go and check all the nested list returning each list containing the element. Or whatever behaviour you need.

iGian
  • 11,023
  • 3
  • 21
  • 36
  • I'd be wary of using `e.__class__ == list` or `isinstance(e, list)`, since there are other iterable types, like `tuple`s, that you'd expect this kind of code to work on – Green Cloak Guy Apr 15 '21 at 14:02