negatives and positives in lists
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 st开发者_StackOverflow中文版art with my coding though. Any help would be great thanks!
example:
negpos([-5,5,6,-8,9])
should return:
[-13, 20]
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.
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.
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.
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
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).
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]
精彩评论