Reputation: 251
I'm trying to write a function that allows me to add only the positive numbers in a list and only the negative numbers in a list. I don't know where to start with my coding though. Any help would be great thanks!
example:
negpos([-5,5,6,-8,9])
should return:
[-13, 20]
Upvotes: 3
Views: 274
Reputation: 56624
import functools
import operator
ltzero = functools.partial(operator.ge, 0) # 0>=num -> num<0
gtzero = functools.partial(operator.le, 0) # 0<=num -> num>0
def negpos(lst):
return [sum(filter(ltzero, lst)), sum(filter(gtzero, lst))]
negpos([-5,5,6,-8,9]) # -> [-13, 20]
Upvotes: 0
Reputation: 41486
Using sum
with a filtered generator expression is the easiest way to add up a subset of a sequence:
positive_tally = sum(x for x in seq if x > 0)
negative_tally = sum(x for x in seq if x < 0)
Combining those into a single negpos
function would be easy enough, but probably unnecessary unless you're doing this in several different places.
Out of curiousity, I decided to do the actual timing comparison between the generator expression approach and the simple for
loop:
code1 = """
data = [-5,5,6,-8,9]
def negpos(seq):
neg, pos = 0, 0
for x in seq:
if x >= 0:
pos += x
else:
neg += x
return neg, pos
"""
code2 = """
data = [-5,5,6,-8,9]
def negpos(seq):
neg = sum(x for x in seq if x < 0)
pos = sum(x for x in seq if x > 0)
return neg, pos
"""
command = "negpos(data)"
timer1 = timeit.Timer(command, code1)
timer2 = timeit.Timer(command, code2)
timer1.repeat()
timer2.repeat()
On my system, the dedicated for
loop comes out as being roughly twice as fast (that's not particularly surprising, since the loop is executed twice with the generator based approach, but it is still interesting to confirm it).
Upvotes: 0
Reputation: 15172
Generator expressions can make life easy and highly efficient:
def negpos( inlist ):
p = sum(x for x in inlist if x > 0)
n = sum(x for x in inlist if x < 0)
return (n,p)
It might also be more appropriate to return a fixed tuple than a list, which I have done.
Upvotes: 1
Reputation: 25599
without any fancy stuff
>>> neg=0
>>> pos=0
>>> for i in [-5,5,6,-8,9]:
... if i<0: neg+=i
... if i>0: pos+=i
...
>>> print neg,pos
-13 20
Upvotes: 0
Reputation: 4879
Check out filter
and sum
. The first argument to filter
is a function that returns True if the value should be included, and False if it should not. Pass a function to it the first time that only selects integers less than 0, and the second time pass one that only selects integers greater than 0, then pass the resulting list to sum
. If you need help past that, just add a comment and I'll help, but I think you'll learn more than if I just give you straight source code.
Upvotes: 2
Reputation: 881133
Try this on for size:
def negpos (lst):
(neg, pos) = (0, 0)
for elem in lst:
if elem < 0:
neg = neg + elem
else:
pos = pos + elem
return [neg, pos]
print negpos ([-5,5,6,-8,9])
It simply maintains two accumulators and adds to the relevant one. The output is:
[-13, 20]
as desired.
Upvotes: 7