Рефакторинг рекурсивной функции "появления"
def recursive_count(target, nested_num_list):
# This code finds all occurrences of "target" in "nested_num_list"
# Rewrite this code without a while/for loop that achieves
# the same results. Basically using only recursive calls and if's.
count = 0
i = 0
while i < len(nested_num_list):
if nested_num_list[i] == target:
count += 1
if type(nested_num_list[i]) == type([]):
count += recursive_count(target, nested_num_list[i])
i += 1
return count
Это был бонусный вопрос (прочитайте хэштеги), который появился в моем классе вычислений. Я пробовал параметры по умолчанию, возился с я и подсчитывал множество способов, но я не могу его получить. Как бы вы прекрасны люди?
Ответы
Ответ 1
Вот еще один подход для Python 3 (который легко переводится на python 2). Никакая модификация входных параметров или использование других функций (кроме isinstance
):
def recursive_count(target, nested_num_list):
if nested_num_list == []:
return 0
if isinstance(nested_num_list, int):
return nested_num_list == target
x, *y = nested_num_list
# x, y = nested_num_list[0], nested_num_list[1:] # Python 2
return recursive_count(target, x) + recursive_count(target, y)
>>> recursive_count(1, [1,2,3,[1,1,1],[1]])
5
Ответ 2
def recursive_count(target, nested_num_list):
count = 0
# Make sure there still stuff left.
if len(nested_num_list) is 0:
return 0
item = nested_num_list.pop(0)
if type(item) == type([]):
count += recursive_count(target, item)
elif target == item:
count += 1
count += recursive_count(target, nested_num_list)
return count
Если вы не возражаете при изменении входных параметров, вы можете просто каждый раз выставлять первый элемент из списка и передавать его обратно.
Изменить: добавлена обработка вложенности.
Ответ 3
Я бы написал рекурсивный flattener и использовал его вывод.
def flattener(left, right):
try:
res = reduce(flattener, right, left)
except TypeError:
left.append(right)
res = left
return res
>>> nested_list = [[0], [1, [2, 3]], [4, 5], [6, [7], [8, 9]], 10, [[[[11]]]], [], 12]
>>> flattened_list = reduce(flattener, nested_list, [])
>>> flattened_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Go on with flattened_list ...
Изменить: для этого нужна одна единственная функция, а здесь версия без isinstance
или явная проверка длины или индексирование и только с одним inline-if
:
def countin(seq, predicate):
try:
iterseq = iter(seq)
except TypeError:
return 1 if predicate(seq) else 0
try:
head = iterseq.next()
except StopIteration:
return 0
c = countin(head, predicate)
c += countin(iterseq, predicate)
return c
>>> count_in(nested_list, lambda x: x % 2 == 0) # count all even numbers
7
>>> len(filter(lambda x: x % 2 == 0, reduce(flattener, nested_list, [])))
7
Ответ 4
def recursive_count(target, nested_num_list):
return (recursive_count(nested_num_list[1:]) + (target == nested_num_list[0])) if nested_num_list else 0