Глубина подсчета или самый глубокий уровень, на который переходит вложенный список

У меня есть реальная проблема (и головная боль) с заданием...

Я учусь на вводном уроке программирования, и мне нужно написать функцию, которая по списку вернет «максимальную» глубину, к которой он идет... Например: [1,2,3] вернет 1, [ 1,[2,3]] вернет 2...

Я написал этот фрагмент кода (это лучшее, что я мог получить T_T)

def flat(l):
    count=0
    for item in l:
        if isinstance(item,list):
            count+= flat(item)
    return count+1

Тем не менее, очевидно, что это не работает должным образом, потому что если есть списки, которые не учитывают максимальную глубину, он все равно поднимает счетчик...

Например: когда я использую функцию с [1,2,[3,4],5,[6],7], она должна возвращать 2, но возвращает 3...

Будем очень благодарны за любые идеи или помощь ^^ большое спасибо!! Я уже несколько недель борюсь с этим...


person dhcarmona    schedule 18.05.2011    source источник
comment
Я думаю, вам нужно слово «глубина», а не глубина.   -  person duffymo    schedule 18.05.2011
comment
В качестве примечания: проверьте PEP-8. Будет хорошо сразу сформировать стильные привычки. Для начала используйте L для списка, а не l (который выглядит как 1).   -  person orokusaki    schedule 18.05.2011
comment
@duffymo Спасибо ^^ мой плохой, я думаю, довольно ясно, что английский не мой родной язык :-)   -  person dhcarmona    schedule 18.05.2011
comment
@orokusaki Это действительно интересно ^^ спасибо! Я даже не знал, что такое существует...   -  person dhcarmona    schedule 18.05.2011
comment
+1 за то, что ясно дал понять, что это домашнее задание, а затем правильно задал вопрос. Вопрос и интересен, и показывает, что было опробовано до сих пор.   -  person Wilduck    schedule 18.05.2011


Ответы (13)


В ширину, без рекурсии, а также работает с другими типами последовательностей:

from collections import Sequence
from itertools import chain, count

def depth(seq):
    for level in count():
        if not seq:
            return level
        seq = list(chain.from_iterable(s for s in seq if isinstance(s, Sequence)))

Та же идея, но с гораздо меньшим потреблением памяти:

from collections import Sequence
from itertools import chain, count

def depth(seq):
    seq = iter(seq)
    try:
        for level in count():
            seq = chain([next(seq)], seq)
            seq = chain.from_iterable(s for s in seq if isinstance(s, Sequence))
    except StopIteration:
        return level
person pillmuncher    schedule 18.05.2011
comment
это сломает последовательность со строками. например, depth(["a"]) сломается - person asdf; 21.07.2016
comment
просто расширьте третью последнюю строку, например seq = chain.from_iterable(s for s in seq if isinstance(s, Sequence) and not isinstance(s, str)), и она также будет работать со строковыми элементами - person Max F.; 04.06.2018

Вот один из способов написать функцию

depth = lambda L: isinstance(L, list) and max(map(depth, L))+1

Я думаю, что вам не хватает идеи использовать max()

person John La Rooy    schedule 18.05.2011
comment
Спасибо ^^ Мне нравится, как вы, ребята, можете упростить каждую функцию, используя лямбда ^^ Я надеюсь, что когда-нибудь смогу это сделать. - person dhcarmona; 18.05.2011
comment
Это разбивается на пустые списки, просто к вашему сведению - person Conor O'Brien; 11.01.2017
comment
Именованные лямбда-выражения — плохая практика. Вместо этого используйте def: def depth(L): return isinstance(L, list) and max(map(depth, L))+1 - person wjandrea; 14.05.2021

Давайте сначала немного перефразируем ваши требования.

Глубина списка на единицу больше, чем максимальная глубина его подсписков.

Теперь это можно перевести непосредственно в код:

def depth(l):
    if isinstance(l, list):
        return 1 + max(depth(item) for item in l)
    else:
        return 0
person hammar    schedule 18.05.2011
comment
Код необходимо исправить для пустых элементов списка, из-за которых генератор создает пустую последовательность для max arg, что приводит к ошибке. - person Basel Shishani; 04.03.2015
comment
@Basel Похоже, что минимальное исправление добавляет if l else 1 после вызова max(). - person wjandrea; 14.05.2021

легко с рекурсией

def flat(l):
    depths = []
    for item in l:
        if isinstance(item, list):
            depths.append(flat(item))
    if len(depths) > 0:
        return 1 + max(depths)
    return 1
person Eduardo    schedule 18.05.2011

Сделал это в одной строке python :)

наслаждаться

def f(g,count=0): return count if not isinstance(g,list) else max([f(x,count+1) for x in g])
person systemizer    schedule 18.05.2011

Способ, который не требует дополнительных модулей и имеет одинаковую скорость, независимо от глубины:

def depth(nested):
    instring = False
    count = 0
    depthlist = []
    for char in repr(nested):
        if char == '"' or char == "'":
            instring = not instring
        elif not instring and ( char == "[" or char == ")" ):
            count += 1
        elif not instring and ( char == "]" or char == ")" ):
            count -= 1
        depthlist.append(count)
    return(max(depthlist))

По сути, это преобразует список в строку, используя repr(). Затем для каждого символа в этой строке, равного «(» или «[», увеличивается переменная count. для закрывающих скобок уменьшается count. Затем он возвращает максимум, которого достиг count.

person user3315473    schedule 07.05.2014

Оскорбительный способ: скажите, что ваш список называется mylist.

mybrackets = map(lambda x: 1 if x=='[' else -1, [x for x in str(mylist) if x=='[' or x==']'])  
maxdepth = max([sum(mybrackets[:i+1]) for i in range(len(mybrackets))])

Это преобразует ваш список в список открывающих и закрывающих скобок, а затем находит наибольшее количество открывающих скобок, которые встречаются до появления соответствующей закрывающей скобки.

person sans    schedule 18.05.2011

Я расширил ответ хаммара для каждой итерации (строки отключены по умолчанию):

def depth(arg, exclude=None):
    if exclude is None:
        exclude = (str, )

    if isinstance(arg, tuple(exclude)):
        return 0

    try:
        if next(iter(arg)) is arg:  # avoid infinite loops
            return 1
    except TypeError:
        return 0

    try:
        depths_in = map(lambda x: depth(x, exclude), arg.values())
    except AttributeError:
        try:
            depths_in = map(lambda x: depth(x, exclude), arg)
        except TypeError:
            return 0

    try:
        depth_in = max(depths_in)
    except ValueError:
        depth_in = 0

    return 1 + depth_in
person Marco Sulla    schedule 29.02.2016

Если вы ищете быстрое решение

def getDepth(matrix):
    try:
        len(matrix)
        return getDepth(matrix[0]) + 1
    except:
        return 0
person Nathan Barrett    schedule 23.06.2020
comment
Попробуйте ввести getDepth(["222"]) в свой интерпретатор, затем.... - person Ulf Aslak; 17.05.2021

Короткое дополнение к тому, что было сказано, чтобы он мог обрабатывать и пустые списки:

def list_depth(list_of_lists):
    if isinstance(list_of_lists, list):
        if(len(list_of_lists) == 0):
            depth = 1
        else:
            depth = 1 + max([list_depth(l) for l in list_of_lists])
    else:
        depth = 0
    return depth
person David    schedule 21.09.2015

В Numpy вы можете преобразовать структуру данных в numpy array и использовать ее библиотечные функции. arr.shape задает длину каждого слоя, поэтому мы можем len() определить форму и получить глубину структуры:

import numpy as np

def f( lists )
  arr = np.array( lists )
  return len(arr.shape)

f( [[[1,2],[3,4]],[[3,4],[5,6]]] ) # results in 3
f( [[1,2],[3,4]] ) # results in 2
f( [1,2] )  # results in 1
f( [] )  # results in 1

Документы Numpy для формы: https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.shape.html

person pds    schedule 09.07.2019

вы также можете сделать это рекурсивно, используя только python:

def depth(L,d):
    max = d
    for i in range(len(L)):
        if type(L[i])==list :
            a = depth(L[i],d+1)
            if a>max :
                 max = a
    return(max)

эта функция является рекурсивной, и что она делает, так это то, что она просто переходит к максимальной глубине вашего списка, считая, насколько глубок этот список, и когда она поднимается обратно, она сохраняет только самую большую глубину, зарегистрированную среди всех вложенных списков.

person Julien    schedule 09.08.2020

Решение @John отличное, но для решения пустых списков, таких как [], [[]] или дополнительных вложенных списков, вам может потребоваться сделать что-то вроде этого

depth = lambda L: isinstance(L, list) and (max(map(depth, L)) + 1) if str(L) else 1
person onerhao    schedule 27.09.2016