2016-10-05 3 views
1

Я экспериментирую с рекурсивными функциями. Моя цель состоит в том, чтобы произвести:Использование списка для создания списка списков в рекурсивной функции

функцию combo, которая генерирует все невозрастающую серии, которые добавляют до п

Некоторые примеры входов/выходов:

>>> print (combo(3)) 
[[3], [2, 1], [1, 1, 1]] 
>>> print (combo(4)) 
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] 
>>> print (combo(5)) 
[[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]] 

После того, как много проб и ошибок, я придумал следующую функцию, которая делает именно то, что я хочу:

Мой вопрос: Есть ли способ (pythonic или нет), чтобы вернуть этот же результат, используя единое понимание списка, без добавления и расширения res?

Вот две вещи, которые я пробовал, наряду с их изуродованные результаты:

return [[i] if i == n else [[i] + x for x in combo(n - i, min(n - i, i))] for i in range(limit, 0, -1)] 
# lists get deeper: [[4], [[3, 1]], [[2, 2], [2, [1, 1]]], [[1, [1, [1, 1]]]]] 

return [[i if i == n else ([i] + x for x in combo(n - i, min(n - i, i))) for i in range(limit, 0, -1)]] 
# parentheses interpreted as generator: [[4, <generator object combo.<locals>.<listcomp>.<genexpr> at 0x01D84E40>, etc.]] 

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

ответ

4

Преобразовать расширения в добавлении и становится легче обращал внимание, как преобразовать это:

res = [] 
for i in range(limit, 0, -1): 
    if i == n: 
     res.append([i]) 
    else: 
     # this is the generator expression pulled out of the res.extend() call 
     for x in combo(n - i, min(n - i, i)): 
      res.append([i] + x) 

Теперь вы можете переместить i == n случай в другую ветвь (используя переменную помощнику items здесь для удобства чтения):

res = [] 
for i in range(limit, 0, -1): 
    items = [[]] if i == n else combo(n - i, min(n - i, i)) 
    for x in items: 
     res.append([i] + x) 

Если i == n, это вызывает итерацию цикла один раз и производить пустой список, так вы фактически получаете res.append([i]).

Это может затем тривиальным преобразовать в список понимания (встраивание items в петлю for):

return [ 
    [i] + x 
    for i in range(limit, 0, -1) 
    for x in ([[]] if i == n else combo(n - i, min(n - i, i)))] 

Wether или нет должны другое дело; это едва ли легче читать.

+0

Работает с последним правлением (круглые скобки). Большое спасибо за вдумчивый ответ! – brianpck

+0

@brianpck: Да, я удивлен этим, поскольку выражение [условное выражение] (https://docs.python.org/3/reference/expressions.html#conditional-expressions) является самым верхним компонентом выражения 'expression' правило в грамматике Python, которое является частью правила ['expression_list'] (https://docs.python.org/3/reference/expressions.html#expression-lists), которое [' for' принимает] (https: //docs.python.org/3/reference/compound_stmts.html#the-for-statement). Я еще раз посмотрю, почему это проблема. –

+0

Не зная слишком много о правилах синтаксиса, кажется, что 'if' считается частью синтаксиса понимания списка условий, например. '[i для i в x, если i == 1]' – brianpck