开发者

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]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜