【问题标题】:Reversing a list using recursion in python [duplicate]在python中使用递归来反转列表[重复]
【发布时间】:2016-03-21 14:07:35
【问题描述】:
def revlist(lst):
    if len(lst) == 1:
        return lst
    else:
        return lst[(len(lst) - 1)

我已经走到这一步了,但我不知道下一步该做什么。我正在为考试练习递归。如果有人可以提供帮助,我将不胜感激。

【问题讨论】:

  • 要了解递归的基础知识,this 可能会对您有所帮助。
  • 你没有递归(你从不在 revlist 中调用 revlist)并且你总是返回一个元素,你期望如何得到一个反向列表?你可能应该多学习一点;)
  • 是的,我知道我应该这样做,但这也不完整,但我有点卡住了:(
  • @thefourtheye 阅读您的评论,我完全希望它在逗号之后以“您首先必须了解递归”结尾。

标签: python list python-2.7 python-3.x recursion


【解决方案1】:

基本情况是您没有列表,因此您想返回空列表。

递归的情况是你做的,所以你想把最后一个元素添加到列表其余部分的递归调用中。

def revlist(lst):
    if not lst:
        return lst
    # Create a list containing only the last element
    last = [lst[-1]]
    # Rest contains all elements up to the last element in `lst`
    rest = lst[:-1]
    # Prepend last to recursive call on `rest`
    return last + revlist(rest)

这是我写的驱动程序:

lst = [1, 2, 3, 4, 5]
print(revlist(lst))

返回:

12:03 $ python test.py 
[5, 4, 3, 2, 1]

这适用于所有可迭代对象。

【讨论】:

  • 不用创建2个变量,调用栈就够了
  • 我明白这一点。我这样做是为了清楚起见,因为 OP 似乎是初学者。
  • 你是对的,明确的答案
【解决方案2】:

想想你要为每个递归调用实现什么。 thefourtheye 在他的评论中提到的链接很好地说明了如何使用递归对列表求和:

listSum([1, 3, 4, 5, 6]) = 1 + listSum([3, 4, 5, 6])
                         = 1 + (3 + listSum([4, 5, 6]))
                         = 1 + (3 + (4 + listSum([5, 6])))
                         = 1 + (3 + (4 + (5 + listSum([6]))))
                         = 1 + (3 + (4 + (5 + (6 + listSum([])))))

以此为基点,您将如何实现反向列表?它可能看起来像:

revlist([1, 3, 4, 5, 6]) = [6] + revlist([1, 3, 4, 5])
                         = [6] + ([5] + revlist([1, 3, 4]))
                         = etc etc
                         = [6] + ([5] + ([4] + ([3] + ([1] + revlist([])))))

这会更简洁地显示您想要实现的目标。最后,这就是你会得到的。

def revlist(lst):
    if not lst:
        return []
    else:
        return lst[-1:] + revlist(lst[:-1])

【讨论】:

  • @erip 也不是我,但我在各地都收到了幻影般的反对票,所以一个人只需要接受它并接受代表的打击 sigh
  • 越简单越不关注
【解决方案3】:

您的简单情况很好,如果列表的长度为 1(或更小),只需返回列表。事实上,我们可以简单地检查列表是否为空(通过发出if not lst)。如果列表较大,则必须考虑如何在递归情况下简化问题。 换句话说,你可以这样表述: 如果列表长于 1,请给我该列表的最后一个元素,当我反转给定列表时得到的列表扩展了该列表,而其中没有最后一个元素。后一个列表比原始列表小一个,因此问题被简化了。

在代码中:

def reverse(lst):
    if not lst: # this will be true if lst == []
        return lst
    return lst[-1:] + reverse(lst[:-1]) # recursive case

# Demo
print(reverse([1,2,3,4,5])) # [5, 4, 3, 2, 1]

【讨论】:

    【解决方案4】:

    另一种方式

    def revlist(lst):
        if len(lst) == 0:
            return ([])
        else:
            return (revlist(lst[1:]) + [lst[0]] )
    

    【讨论】:

    • 哦不,去掉那些括号!
    • 对不起口齿不清的方式:D
    【解决方案5】:

    使用 fold

    的思想编写的版本

    我们需要一个称为 cons 的函数(来自 lisp/scheme 等)。它接受一个元素和一个列表,并将该元素添加到列表的头部(开始)。请注意,在 python 中,这不是有效的。

    def cons(x,xs):
      return [x] + xs
    

    现在是 fold 函数(严格来说是左折叠)。这本身就是一个函数,可用于许多事物(请参阅链接),python 等价物可能是reduce。请注意,它需要一个函数 f 并将此函数应用于列表的头部和变量 acc(累加器的缩写)

    def foldl(f,acc,xs):
      if not xs:         
        return acc
      head, *tail = xs
      return foldl(f, f(head,acc), tail)
    

    现在我们可以编写一个递归的 reverse 版本(因为 fold 是递归的)

    def reverse(xs):
      return foldl(cons, [], xs)
    

    所以折叠体现了递归函数的思想。例如,如果我们想对一个数字列表进行递归求和,我们可以将其定义为:

    from operator import add # this is just '+' as a function
    def sum(xs):
      return foldl(add, 0, xs)
    

    如果我们要定义一个右折叠,如下所示:

    def foldr(f,acc,xs):
      if not xs:         
        return acc
      head, *tail = xs
      return f(head, foldr(f, acc, tail))
    

    然后调用foldr(cons, [], xs) 将返回一个与初始列表相同的列表。

    【讨论】:

    • 可爱的解决方案。非常口齿不清。 +1
    猜你喜欢
    • 2022-08-12
    • 2010-09-17
    • 2018-12-03
    • 2016-09-26
    • 2014-04-13
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 2017-06-22
    相关资源
    最近更新 更多