views:

286

answers:

5

I have a list of integers and I need to count how many of them are > 0.
I'm currently doing it with a list comprehension that looks like this:

sum([1 for x in frequencies if x > 0])

It seems like a decent comprehension but I don't really like the "1"; it seems like a bit of a magic number. Is there a more Pythonish way to do this?

+2  A: 

You could use len() on the filtered list:

len([x for x in frequencies if x > 0])
sth
even better, to use a generator (strip [ and ])
valya
You could use filter with this to make it look more clear.len(filter(lambda x: x > 0, frequencies))
Jonathan Sternberg
@valya: That won't work with a generator
sth
@Jonathan: I'd say it's a matter of taste if you prefer `filter()` or a list comprehension, but usually list comprehensions are preferred to functional programming style. (And the OP asked for a list comprehension.)
sth
@sth: the OP actually only said (s)he is using a decent list comprehension right now, but didn't specifically ask for one. But your main point still holds, of course.
Peter Jaric
+8  A: 

A slightly more Pythonic way would be to use a generator instead:

sum(1 for x in frequencies if x > 0)

This avoids generating the whole list before calling sum().

Greg Hewgill
+1 because this is a commonly overlooked way of doing a comprehension. If you're evaluating a list comprehension from within a function call, you can omit the `[]`.
jathanism
+10  A: 
sum(x > 0 for x in frequencies)

bool is a subclass of int:

In [15]: isinstance(True,int)
Out[15]: True

and True's value is 1:

In [16]: True==1
Out[16]: True
unutbu
A variation: [x > 0 for x in frequencies].count(True)
Peter Jaric
@Peter: note that your suggestion loops twice over the data; once to build the output list, and twice to count True values.
ΤΖΩΤΖΙΟΥ
@ΤΖΩΤΖΙΟΥ: Yes, of course, thanks for the info!
Peter Jaric
A: 

How about this?

reduce(lambda x, y: x+1 if y > 0 else x, frequencies)

EDIT: With inspiration from the accepted answer from @~unutbu:

reduce(lambda x, y: x + (y > 0), frequencies)

Peter Jaric
I wish I had got a comment to go with that down vote to learn by my mistakes. Please?
Peter Jaric
There seems to be a trend away from lambda functions toward list comprehensions.
AntiRush
I wasn't one to downvote you; however I would gather that people tend to frown upon `reduce`, it being phased out etc (by Guido proclamation). I like `reduce`, but I too frown upon its use in this case, since the `sum(x > 0…)` variant seems more straightforward to me.
ΤΖΩΤΖΙΟΥ
+3  A: 

This works, but adding bools as ints may be dangerous. Please take this code with a grain of salt (maintainability goes first):

sum(k>0 for k in x)
Arrieta
Adding booleans as integers is guaranteed to work in Python 2 and 3: http://stackoverflow.com/questions/2764017/is-false-0-and-true-1-in-python-an-implementation-detail-or-guaranteed-by-t
EOL
+1 for the warning, though. :)
EOL