8

给定一个数字列表,我正在尝试编写一个代码来找出连续元素之间的差异。例如,A = [1, 10, 100, 50, 40]函数的输出应该是[0, 9, 90, 50, 10]. 这是我到目前为止尝试使用递归的内容:

def deviation(A):
    if len(A) < 2:
        return
    else:
        return [abs(A[0]-A[1])] + [deviation(A[1: ])]

但是,我得到的输出(使用上面的 A 示例作为输入)是[9, [90, [50, [10, None]]]]. 如何正确格式化括号?(我试过猜测和检查,但这是我得到的最接近的)我如何写这个,它从前一个元素中减去当前元素,而不会出现第一个元素的索引错误?我仍然希望输出列表的第一个元素为零,但我不知道如何使用递归来解决这个问题,出于某种原因,这对我来说似乎是最好的路线。

4

6 回答 6

13

你可以做:

[y-x for x, y in zip(A[:-1], A[1:])] 


>>> A = [1, 10, 100, 50, 40]
>>> [y-x for x, y in zip(A[:-1], A[1:])]
[9, 90, -50, -10]

请注意,如果右侧较小,差异将是负数,您可以轻松解决此问题(如果您认为此错误),我将为您留下解决方案。

解释:

您可以获得的最佳解释是简单地打印列表理解的每个部分。

  • A[:-1]返回没有最后一个元素的列表:[1, 10, 100, 50]
  • A[1:]返回没有第一个元素的列表:[10, 100, 50, 40]
  • zip(A[:-1], A[1:])返回[(1, 10), (10, 100), (100, 50), (50, 40)]
  • 最后一步是简单地返回每个元组中的差异。
于 2014-07-07T15:35:32.550 回答
7

最简单(最懒惰)的解决方案是使用 numpy 函数 diff:

>>> A = [1, 10, 100, 50, 40]
>>> np.diff(A)
array([  9,  90, -50, -10])

如果您想要差异的绝对值(正如您的问题所暗示的那样),那么取数组的绝对值。

于 2014-07-14T17:29:58.990 回答
2
[abs(j-A[i+1]) for i,j in enumerate(A[:-1])]
于 2014-07-07T15:46:41.603 回答
1

实际上递归是一种矫枉过正:

def deviation(A):
    yield 0
    for i in range(len(A) - 1):
        yield abs(A[i+1] - A[i])

例子:

>>> A = [3, 5, 2]
>>> list(deviation(A))
[0, 2, 3]

编辑:然而,另一个更简单、更有效的解决方案是:

def deviation(A):
    prev = A[0]
    for el in A:
        yield abs(el - prev)
        prev = el
于 2014-07-07T15:35:17.503 回答
1

你可以做一个列表理解:

>>> A = [1, 10, 100, 50, 40]
>>> l=[A[0]]+A
>>> [abs(l[i-1]-l[i]) for i in range(1,len(l))]
[0, 9, 90, 50, 10]
于 2014-07-07T15:53:24.403 回答
1

对于更符合您原始方法的更长递归解决方案:

def deviation(A) :
    if len(A) < 2 :
        return []
    else :
        return [abs(A[0]-A[1])] + deviation(A[1:])

您的括号问题与您的递归调用有关。由于您有[deviation(a[1: ])]自己的[]括号,因此每次递归调用都将创建一个新列表,从而在列表中产生许多列表。

为了解决这个None问题,只需将您的基本情况更改为一个空列表[]。现在,您的函数将在递归列表的末尾添加“无”,而不是None空白return

于 2014-07-07T17:18:50.467 回答