Make a "sub" function

a function like “sum” that instead of adding, subtracts

it’s easy to make a function like that in python, but It would save me a lot of work if they made this function

Moving to help category because there are already plenty of solutions to this.

what solutions?

Could you show an example of the work you had to do because of it, and how you think it would be easier if you had access to this “sub”?

Could you show a detailed explanation of what the interface and semantics should be?

In particular, is there a reason why this is different from “the first element, minus the sum of the other elements”, which is trivial to express in terms of the existing sum?

1 Like

Ugly, but:

>>> sub = lambda x, *rest: x-sum(rest)
>>> sub(10000, 8)
9992
>>> sub(10000, 8, 2, 4)
9986
>>>```

That doesn’t take an iterable, unlike sum.

Perhaps:

def sub(iterable):
    iterator = iter(iterable)
    try:
        first = next(iterator)
    except StopIteration:
        raise ValueError # or return 0?
    return first - sum(iterator)

@blhsing Another, which might differ less often from the normal left-to-right calculation:

def sub1(iterable):
    iterator = iter(iterable)
    try:
        first = next(iterator)
    except StopIteration:
        raise ValueError # or return 0?
    return first - sum(iterator)

def sub2(iterable):
    iterator = iter(iterable)
    for first in iterator:
        return -sum(iterator, -first)
    raise ValueError # or return 0?

a, b, c = iterable = 0.1, 0.2, 0.6
print(a - b - c)
print(sub1(iterable))
print(sub2(iterable))

Output (Attempt This Online!):

-0.7
-0.7000000000000001
-0.7
1 Like

And with a, b, c = iterable = [1e308] * 3:

-1e+308
-inf
-1e+308

Addition is associative, subtraction is not.

sum([1,2,3]) == (1 + 2) + 3 == 1 + (2 + 3) == 6

What should difference([1,2,3]) compute?

  1. 1 - (2 - 3) == 1 - (-1) == 2, or
  2. (1 - 2) - 3 == -1 -3 == -4, or
  3. -1 + -2 + -3 == -6 (for sake of argument; this isn’t really equivalent to what I think you want)
3 Likes

Very good point, although if you want to be truly faithful to the original expression of a - b - c you can use functools.reduce and operator.sub:

from operator import sub
from functools import reduce

def sub2(iterable):
    iterator = iter(iterable)
    for first in iterator:
        return -sum(iterator, -first)
    raise ValueError # or return 0?

def sub3(iterable):
    iterator = iter(iterable)
    for first in iterator:
        return reduce(sub, iterator, first)
    raise ValueError # or return 0?

a, b, c = iterable = -.0, -.0, -.0
print(a - b - c) # outputs 0.0
print(sub2(iterable)) # outputs -0.0
print(sub3(iterable)) # outputs 0.0
1 Like

Yeah, that’s why I said “differ less often” :slight_smile:

If you’re ok with reduce’s TypeError for empty iterables, you can also just do

def sub4(iterable):
    return reduce(sub, iterable)
1 Like