Reputation: 149
Given a list of numbers, I am trying to write a code that finds the difference between consecutive elements. For instance, A = [1, 10, 100, 50, 40]
so the output of the function should be [0, 9, 90, 50, 10]
. Here is what I have so far trying to use recursion:
def deviation(A):
if len(A) < 2:
return
else:
return [abs(A[0]-A[1])] + [deviation(A[1: ])]
The output I get, however, (using the above example of A as the input) is [9, [90, [50, [10, None]]]]
. How do I properly format my brackets? (I've tried guessing and checking but I this is the closest I have gotten) And how do I write this where it subtracts the current element from the previous element without getting an index error for the first element? I still want the first element of the output list to be zero but I do not know how to go about this using recursion and for some reason that seems the best route to me.
Upvotes: 8
Views: 15688
Reputation: 56467
Actually recursion is an overkill. An efficient solution is:
def deviation(seq):
prev = seq[0]
for current in seq:
yield abs(current - prev)
prev = current
Example:
>>> seq = [3, 5, 2]
>>> list(deviation(seq))
[0, 2, 3]
EDIT: First suggestion (discarded after discussion in the comments section):
def deviation(A):
yield 0
for i in range(len(A) - 1):
yield abs(A[i+1] - A[i])
Upvotes: 2
Reputation: 1521
The simplest (laziest) solution is to use the numpy function diff:
>>> A = [1, 10, 100, 50, 40]
>>> np.diff(A)
array([ 9, 90, -50, -10])
If you want the absolute value of the differences (as you've implied by your question), then take the absolute value of the array.
Upvotes: 8
Reputation: 121
For a longer recursive solution more in line with your original approach:
def deviation(A) :
if len(A) < 2 :
return []
else :
return [abs(A[0]-A[1])] + deviation(A[1:])
Your bracket issue is with your recursive call. Since you have your [deviation(a[1: ])]
in its own []
brackets, with every recursive call you're going to be creating a new list, resulting in your many lists within lists.
In order to fix the None
issue, just change your base case to an empty list []
. Now your function will add 'nothing' to the end of your recursively made list, as opposed to the inherent None
that comes with a blank return
'
Upvotes: 1
Reputation: 103783
You can do a list comprehension:
>>> 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]
Upvotes: 1
Reputation: 95958
You can do:
[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]
Note that the difference will be negative if the right side is smaller, you can easily fix this (If you consider this wrong), I'll leave the solution for you.
Explanation:
The best explanation you can get is simply printing each part of the list comprehension.
A[:-1]
returns the list without the last element: [1, 10, 100, 50]
A[1:]
returns the list without the first element: [10, 100, 50, 40]
zip(A[:-1], A[1:])
returns [(1, 10), (10, 100), (100, 50), (50, 40)]
Upvotes: 13