Reputation: 179
I've a list of integers that I want to subtract from each other in consecutive order. I want to be able to use the code for any size list of integers, even if I don't know the number of integers.
What I've so far:
a = [10, 9, 8] # Example list with 3 integers
sub = 0
for i, n in enumerate(a):
sub = a[i] - a[i+1]
print(sub)
My expected answer is -7 because:
10 - 9 = 1
Then 1 - 8 = -7
10 and 9 are the first and second element of the list a
, respectively. I subtract them to get 1. I then take 1 and deduct 8 -- the third element of the list -- from it to get -7.
Instead, I get an error that the list index is out of range. I know why I'm getting this: because when i
hits 2, i+1
becomes 3, and there is no a[3]
element in the list.
Yet for something so simple, I can't seem to figure out how to obtain consecutive indices like this, especially for a list where I wouldn't know the number of elements.
How can I fix this? Should I just use a try-except
clause and break
out of the loop when I get the IndexError
?
Upvotes: 0
Views: 4449
Reputation: 778
If you are just after the total result for the entire list (i.e. [10,9,8]
results in an answer of -7
as opposed to a result of [10, 1, -7]
) then then you simply need to subtract the sum of all the values after the first item. The order of subtraction does not matter.
import numpy as np
a = [10, 9, 8]
sub = a[0] - np.sum(a[1:])
If you want the cumulative result (i.e. result of [10, 1, -7]
) then use the cumsum
function:
sub = np.append(a[0], a[0] - np.cumsum(a[1:]))
Upvotes: 0
Reputation: 1
from functools import reduce
num=[100,20,30,12,15,10]
print(reduce(lambda x,y:x-y,num))
Upvotes: 0
Reputation: 155418
Simpler and faster solution than explicit loops or reduce
: Realizing that a - b - c - ... - n
is equivalent to a - (b + c + ... + n)
, so you can use the sum
function (which is optimized at the C layer for sums that fit in a C long
, only falling back to more expensive Python level int
s if it overflows a C long
).
a = [10, 9, 8] # Example list with 3 integers
sub = a[0] - sum(a[1:])
print(sub)
Note: This makes a shallow copy of most of a
, and requires a sequence type (to support indexing/slicing), not any iterable. You can fix both issues with the slightly longer code:
a = [10, 9, 8] # Example list with 3 integers
aiter = iter(a) # Make iterator from any iterable
sub = next(aiter) - sum(aiter) # Pull first item from iterator, then pass rest to sum
print(sub)
This will be ever-so-slightly slower for small input list
s (fixed overhead from iter
/next
being slightly greater than fixed overhead of indexing/slicing, though slicing has growing overhead of copy that iter
/next
lacks), but the savings on longer inputs would more than make up for it.
Upvotes: 4
Reputation: 1297
Based on your expected output of -7, you need to be subtracting from the running difference prior to the element you're currently on, rather than a[i] - a[i+1]
.
In terms of the index issue, you can resolve it by adding in a logical check to make sure that you have remaining elements in the array by bounding the end point to be len(a) - 1
a = [10, 9, 8] # Example list with 3 integers
sub = a[0]
for i, n in enumerate(a):
if i < (len(a) - 1):
sub = sub - a[i + 1]
print(sub)
Upvotes: 1
Reputation: 60994
You can use functools.reduce
along with operator.sub
from operator import sub
from functools import reduce
a = [10, 9, 8]
reduce(sub, a)
# -7
This is roughly equivalent to
a = [10, 9, 8]
accumulator = a[0]
for x in a[1:]:
accumulator -= x
print(accumulator)
# -7
Upvotes: 1