Alureon
Alureon

Reputation: 179

Subtracting Elements of List

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

Answers (5)

J.Warren
J.Warren

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

user16341628
user16341628

Reputation: 1

from functools import reduce
num=[100,20,30,12,15,10]
print(reduce(lambda x,y:x-y,num))

Upvotes: 0

ShadowRanger
ShadowRanger

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 ints 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 lists (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

John Stark
John Stark

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

Patrick Haugh
Patrick Haugh

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

Related Questions