Глубина подсчета или самый глубокий уровень, в который попадает вложенный список - PullRequest
22 голосов
/ 18 мая 2011

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

Я нахожусь во вводном классе программирования, и мне нужно написать функцию, которая, учитывая список, будет возвращать«максимальная» глубина доходит до ... Например: [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 ...

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

Ответы [ 11 ]

27 голосов
/ 18 мая 2011

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

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

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

11 голосов
/ 18 мая 2011

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

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

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

def depth(l):
    if isinstance(l, list):
        return 1 + max(depth(item) for item in l)
    else:
        return 0
5 голосов
/ 18 мая 2011

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

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
5 голосов
/ 18 мая 2011

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

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
2 голосов
/ 18 мая 2011

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

наслаждайся

def f(g,count=0): return count if not isinstance(g,list) else max([f(x,count+1) for x in g])
1 голос
/ 29 февраля 2016

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

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
1 голос
/ 07 мая 2014

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

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.

1 голос
/ 18 мая 2011

Оскорбительный способ: допустим, ваш список называется mylist
mybrackets = map(lambda x: 1 if x=='[' else -1, [x for x in str(mylist) if x=='[' or x==']'])<br> maxdepth = max([sum(mybrackets[:i+1]) for i in range(len(mybrackets))])

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

0 голосов
/ 09 июля 2019

В 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

0 голосов
/ 27 сентября 2016

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

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

...