Подсчитайте все элементы в списке произвольного вложенного списка без рекурсии
Я только что узнал о рекурсии в Python и завершил присвоения, одним из которых было подсчет всех элементов в списке произвольно вложенных списков. Я искал этот сайт, и все найденные ответы, похоже, используют рекурсивные вызовы. Поскольку было показано, что все, что может быть выражено рекурсивно, может быть выражено итеративно, а итерация предпочтительна в Python, как это будет выполнено без рекурсии или импортированных модулей в Python 2.6 (в качестве учебного упражнения)? (Сам вложенный список будет считаться как элемент, так же как и его содержимое.)
Например:
>>> def element_count(p):
... count = 0
... for entry in p:
... count += 1
... if isinstance(entry, list):
... count += element_count(entry)
... return count
>>> print element_count([1, [], 3])
3
>>> print element_count([1, [1, 2, [3, 4]]])
7
>>> print element_count([[[[[[[[1, 2, 3]]]]]]]])
10
Как это будет написано с помощью итерации?
Ответы
Ответ 1
Вот один из способов сделать это:
def element_count(p):
q = p[:]
count = 0
while q:
entry = q.pop()
if isinstance(entry, list):
q += entry
count += 1
return count
print element_count([1, [], 3])
print element_count([1, [1, 2, [3, 4]]])
print element_count([[[[[[[[1, 2, 3]]]]]]]])
Код поддерживает очередь вещей, на которые нужно смотреть. Всякий раз, когда цикл встречает суб-список, он добавляет его содержимое в очередь.
Ответ 2
Обычно каждая рекурсивная проблема может быть преобразована в итеративную с помощью стека, в этом случае a list
:
def element_count(p):
elements = list(p)
count = 0
while elements:
entry = elements.pop()
count += 1
if isinstance(entry, list):
elements.extend(entry)
return count
Ответ 3
Вы можете найти эту версию element_count
несколько более мощной, чем другие. Он может обрабатывать все контейнеры, поддерживающие итерацию, и он правильно идентифицирует рекурсивные контейнеры как имеющие бесконечное количество элементов.
>>> def element_count(p):
stack, pointers, count = [iter(p)], set([id(p)]), 0
while stack:
for item in stack.pop():
try:
iterator = iter(item)
except TypeError:
pass
else:
location = id(item)
if location in pointers:
return float('inf')
stack.append(iterator)
pointers.add(location)
count += 1
return count
>>> element_count([1, [], 3])
3
>>> element_count([1, [1, 2, [3, 4]]])
7
>>> element_count([[[[[[[[1, 2, 3]]]]]]]])
10
>>> p = [1, 2, 3]
>>> element_count(p)
3
>>> p.append({4, 5, 6})
>>> element_count(p)
7
>>> p.append(p)
>>> element_count(p)
inf
>>>