Python列表递归更改

3

我在尝试递归地将数字序列添加到列表中时遇到了一个错误。例如,如果输入是[5,3,9],我会执行[5+1,3+2,9+3]并输出[6,5,12]。我希望能够递归地实现这个过程,因此我的做法是通过遍历列表中越来越小的一部分并将其加一来完成:

def add_position_recur(lst, number_from=0):
    length = len(lst)
    # base case
    if (length <= 1):
        lst = [x+1 for x in lst]
        print "last is", lst
    else:
        lst = [x+1 for x in lst]
        print "current list is", lst
        add_position_recur(lst[1:], number_from)
        return lst

问题在于,这只是将列表中的每个元素加1。错误在哪里?是与我在基本情况下返回列表的方式有关吗?


number_from 用于什么?在你的代码中它没有任何用处。请注意,当你执行 lst = ... 时,你正在改变 lst 引用的新列表。这不会改变作为参数传递的原始列表。 - logee
3个回答

2
当你递归调用时,你会切片lst,这会创建一个新的列表,它与你返回的不同,因此你只会返回你在第一次调用函数中应用的更改,失去了所有下面的更改。
>>> add_position_recur([1,2,3])
[2, 3, 4]

这应该返回 [2, 4, 6]。在退出时需要考虑重新组装列表以获取更改。
return [lst[0]] + add_position_recur(lst[1:], number_from)

在基本情况下,您需要返回lst:

def add_position_recur(lst, number_from=0):
    length = len(lst)
    # base case
    if (length <= 1):
        lst = [x+1 for x in lst]
        return lst
    else:
        lst = [x+1 for x in lst]
        return [lst[0]] + add_position_recur(lst[1:], number_from)
>>> add_position_recur([1,2,3])
[2, 4, 6]

然而,这是一种相当复杂的递归方法。通常情况下,基本情况是空列表,否则就取头部并向下递归尾部。因此,考虑使用 number_from 来实现以下内容:

def add_position_recur(lst, number_from=1):
    if not lst:
        return lst
    return [lst[0]+number_from] + add_position_recur(lst[1:], number_from+1)

>>> add_position_recur([1,2,3])
[2, 4, 6]

这样做的优点是不改变传入的lst参数。


0
为什么不这样做呢:

def func(lon, after=[]):
    if not l:
        pass
    else:
        v = len(lon) + lon[-1]
        after.append(v)
        func(lon[:-1], after)
        return after[::-1]

你提供的例子中,该函数的输出结果符合你的要求。

0

目前,您只是将1添加到列表中的每个值。

lst = [x+1 for x in lst]

相反地,你应该增加一个变量,这个变量在lst的每次迭代中都会被添加到x上。
lst = [x+(lst.index(x)+1) for x in lst]

该解决方案假定您希望添加到 x 的数字取决于其在列表中相对于列表开头的位置,而不是取决于 x 相对于第一个大于1的元素的位置。也就是说,您想要将 1 或 3 添加到以下列表中值为2的值吗?上面的解决方案会加三。

lst = [0.5, 0.1, 2, 3]

2
不要使用[x+(lst.index(x)+1) for x in lst],当列表中有重复项时它无法正常工作,而且速度非常慢。请使用enumerate[x+(i+1) for i,x in enumerate(lst)] - Dan D.
@DanD。更好的方法是使用enumeratestart参数来避免额外的算术操作:[x+i for i,x in enumerate(lst, start=1)] - lvc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接