37

I have a list, sometimes it is nested, sometimes it is not. Based whether it is nested, the continuation is different. How do I check if this list is nested? True or False should be output.

example:

[1,2,3] --> False

[[1],[2],[3]] --> True

jason
  • 3,811
  • 18
  • 92
  • 147
  • 1
    "the continuation is different" - how? Maybe you just want to [flatten](http://stackoverflow.com/questions/406121/flattening-a-shallow-list-in-python) it? – georg Jun 12 '14 at 09:30
  • 1
    I'm putting it into a `dataframe`. The code for doing that is different if it is flat or nested. Flattening a nested list gives me a different structure to the data. I need to maintain the structure. – jason Jun 12 '14 at 09:34

3 Answers3

65

You can use isinstance and a generator expression combined with any. This will check for instances of a list object within your original, outer list.

In [11]: a = [1, 2, 3]

In [12]: b = [[1], [2], [3]]

In [13]: any(isinstance(i, list) for i in a)
Out[13]: False

In [14]: any(isinstance(i, list) for i in b)
Out[14]: True

Note that any will return True as soon as it reaches an element that is valid (in this case if the element is a list) so you don't end up iterating over the whole outer list unnecessarily.

Ffisegydd
  • 51,807
  • 15
  • 147
  • 125
3

We want to check if elements inside outer-list is an instance of list or not, like @Ffisegydd said we can use a generator expression to build a generator and iterate over it using next(), If any element inside the outer-loop is an instance of list then calling next() on the generator will work otherwise if none of the element inside outer-loops belongs to an instance of list then calling next will raise StopIteration

Best case: If it's a nested loop (we can stop iterating as soon as we see the first instance of list)

Worst case: If it's not a nested loop (We need to iterate over all the elements inside the outerlist)

def is_nested_list(l):
    
    try:
          next(x for x in l if isinstance(x,list))
    
    except StopIteration:
        return False
    
    return True

Anandhu Gopi
  • 61
  • 1
  • 4
0
def get_dict_values(data_structure):
    ''' Get a list with the values of a dictionary items '''

    [*values] = data_structure.values()

    return values

def get_list_values(data_structure, temp):
    ''' Transform a nested list into a one depth level list '''

    for item in data_structure:
        if type(item) == list:
            temp = ReturnDataValues.get_list_values(item, temp)

        elif type(item) == dict:
            dict_values = ReturnDataValues.get_dict_values(item)
            temp = ReturnDataValues.get_list_values(dict_values, temp)

        else:
            temp.append(item)

    return temp

def get_object_values(data_structure, result):
    ''' Get all the values of the elements of an object at all its depth levels '''

    data_type = type(data_structure)

    if data_type == dict:
        values = ReturnDataValues.get_dict_values(data_structure)
        ReturnDataValues.get_object_values(values, result)

    if data_type == list:
        ReturnDataValues.get_list_values(data_structure, result)

    return result


**nested_list** = ['a', 'b', ['c', 'd'], 'e', ['g', 'h', ['i', 'j', ['k', 'l']]] ]
print(get_list_values(nested_list))

Output:

 ['a', 'b', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'l']
  • This is a nice example of why you should never use a mutable type as default value. Have you tried to run it twice? See for example https://florimond.dev/en/posts/2018/08/python-mutable-defaults-are-the-source-of-all-evil/ – Vincenzooo Oct 22 '21 at 21:39