I have an iterable of entries on which I would like to gather some simple statistics, say the count of all numbers divisible by two and the count of all numbers divisible by three.
My first alternative, While only iterating through the list once and avoiding the list expansion (and keeping the split loop refactoring in mind), looks rather bloated:
(alt 1)
r = xrange(1, 10)
twos = 0
threes = 0
for v in r:
if v % 2 == 0:
twos+=1
if v % 3 == 0:
threes+=1
print twos
print threes
This looks rather nice, but has the drawback of expanding the expression to a list:
(alt 2)
r = xrange(1, 10)
print len([1 for v in r if v % 2 == 0])
print len([1 for v in r if v % 3 == 0])
What I would really like is something like a function like this:
(alt 3)
def count(iterable):
n = 0
for i in iterable:
n += 1
return n
r = xrange(1, 10)
print count(1 for v in r if v % 2 == 0)
print count(1 for v in r if v % 3 == 0)
But this looks a lot like something that could be done without a function. The final variant is this:
(alt 4)
r = xrange(1, 10)
print sum(1 for v in r if v % 2 == 0)
print sum(1 for v in r if v % 3 == 0)
and while the smallest (and in my book probably the most elegant) it doesn't feel like it expresses the intent very well.
So, my question to you is:
Which alternative do you like best to gather these types of stats? Feel free to supply your own alternative if you have something better.
To clear up some confusion below:
- In reality my filter predicates are more complex than just this simple test.
- The objects I iterate over are larger and more complex than just numbers
- My filter functions are more different and hard to parameterize into one predicate