【问题标题】:Trying to make recursive solution fully functional试图使递归解决方案功能齐全
【发布时间】:2021-04-08 12:35:50
【问题描述】:

我目前正在做一个递归问题并且我解决了它。现在我想通过用辅助函数替换 for 循环来使解决方案功能齐全,但我不能完全理解这一点。我很确定它是通过一个帮助函数完成的,该函数通过递归调用自身并在每个项目之后对列表进行切片来循环列表,但我似乎没有任何运气。有什么建议吗?

def flatten(arr):
    result = []
    for item in arr:
        if type(item) != type([]):
            result = result + [item]
        else:
            result = result + flatten(item)
    return result

print(flatten([1,[[2],3],[[[4]]]]))
##[1,2,3,4]

【问题讨论】:

  • arr 是什么类型?
  • @IgnacioAlorre 我更新了问题以进行澄清
  • @IgnacioAlorre 我想用自己的函数自己实现它,这样我就能更好地理解一切。
  • @user737163 我关于仅展平一个级别的评论是为了回应其他人的评论。

标签: python recursion functional-programming


【解决方案1】:

你可以使用数学归纳法 -

  1. 如果输入t 为空,则返回基本情况[]
  2. (感应)t 不为空。如果t 中的第一个元素是一个列表,则将其展平并将其与展平的子问题t[1:] 结合起来
  3. (归纳)t 不为空,t 中的第一个元素不是列表。返回t 中的第一个元素和扁平子问题t[1:]
def flatten(t):
  if not t:
    return []                             # 1
  elif isinstance(t[0], list):
    return flatten(t[0]) + flatten(t[1:]) # 2
  else:
    return [t[0]] + flatten(t[1:])        # 3

print(flatten([1,[[2],3],[[[4]]]]))
[1,2,3,4]

与此相同,使用*展开运算符-

def flatten(t):
  if not t:
    return []                                   # 1
  elif isinstance(t[0], list):
    return [ *flatten(t[0]), *flatten(t[1:]) ]  # 2
  else:
    return [ t[0], *flatten(t[1:]) ]            # 3

另一种选择是在分支2 中描述一个新的子问题。而不是

  1. 将第一个元素t[0]展平为x
  2. 将列表的其余部分展平,t[1:],为y
  3. 结合,x + y

不同的子问题可能如下所示 -

  1. 将第一个元素t[0] 与列表的其余部分t[1:] 组合为x
  2. 展平x
def flatten(t):
  if not t:
    return []                         # 1
  elif isinstance(t[0], list):
    return flatten(t[0] + t[1:])      # 2 <-
  else:
    return [ t[0], *flatten(t[1:]) ]  # 3

或者考虑使用生成器 -

def flatten(t):
  if not t:
    return                       # 1
  elif isinstance(t[0], list):
    yield from flatten(t[0])     # 2
    yield from flatten(t[1:])    # 2
  else:
    yield t[0]                   # 3
    yield from flatten(t[1:])    # 3

print(list(flatten([1,[[2],3],[[[4]]]])))
[1,2,3,4]

或者使用像flatmap这样的泛型函数-

def reduce(f, init, t):
  if not t:
    return init
  else:
    return reduce(f, f(init, t[0]), t[1:])

def flatmap(f, t):
  return reduce \
    ( lambda r, v: r + f(v)
    , []
    , t
    )

def flatten(t):
  return flatmap \
    ( lambda v: \
        flatten(v) if isinstance(v, list) else [v]
    , t
    )

print(flatten([1,[[2],3],[[[4]]]]))
[1,2,3,4]

【讨论】:

    【解决方案2】:

    您可以使用functools.reduce 使其按照以下方式工作:

    from functools import reduce
    
    def reducer(a, b):
        return a + (flatten(b) if isinstance(b, list) else [b])
    
    def flatten(arr):
        return reduce(reducer, arr, [])
    
    >>> flatten([1,[[2],3],[[[4]]]])
    [1, 2, 3, 4]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 2015-10-25
      • 1970-01-01
      • 2021-11-03
      • 2018-12-30
      • 2018-11-30
      • 2021-06-22
      相关资源
      最近更新 更多