Most pythonic way of counting matching elements in something iterable
list-comprehension, python
Solution
Having to iterate over the list multiple times isn't elegant IMHO.
I'd probably create a function that allows doing:
twos, threes = countmatching(xrange(1,10),
lambda a: a % 2 == 0,
lambda a: a % 3 == 0)
A starting point would be something like this:
def countmatching(iterable, *predicates):
v = [0] * len(predicates)
for e in iterable:
for i,p in enumerate(predicates):
if p(e):
v[i] += 1
return tuple(v)
Btw, "itertools recipes" has a recipe for doing much like your alt4.
def quantify(seq, pred=None):
"Count how many times the predicate is true in the sequence"
return sum(imap(pred, seq))
Problem
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