2

I have a list, and need to create a count of how many times a condition is met. Is it more pythonic to do this:

cnt = sum([1 for s in a_list if some_condition])

or is this more pythonic:

cnt = 0
  for s in a_list:
    if (some_condition):
      cnt += 1
Dr. Andrew
  • 2,532
  • 3
  • 26
  • 42

3 Answers3

15

Neither.

Use the first one but without creating an unnecessary list in memory:

cnt = sum(1 for s in a_list if some_condition)

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
5

Use the fact, that True used as an integer is 1:

cnt = sum(some_condition(s) for s in a_list)
Daniel
  • 42,087
  • 4
  • 55
  • 81
  • This adds a lot of overhead if `some_condition` isn't already a function you need to call. – chepner May 26 '17 at 12:06
  • 1
    no overhead, `some_condition` can be any expression, e.g. `s > 4`, so it can be faster than DeepSpace's answer. – Daniel May 26 '17 at 12:18
4

You can do it more simply:

cnt = sum(map(condition_func, a_list))

That assumes condition_func is some sort of function that turns an item in the list into True or False.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 2
    It's important to note that if `condition_func` is not a built-in then the performance of `map` might be worse than some of the other alternatives. – DeepSpace May 26 '17 at 11:31
  • @DeepSpace: Do you think `map()` would be worse than Daniel's otherwise equivalent answer? – John Zwinck May 26 '17 at 11:33
  • @DeepSpace could you elaborate a little on that? (or give some reference at least). JohnZwinck - really like the answer (and actually use that kind of things a lot), but summing "True" or "False" values isn't very clear pattern (I've seen a lot of questions here on SO regarding such things). – erhesto May 26 '17 at 11:35
  • 1
    Sorry for the mixup, `map` becomes slower when used with lambdas. It's alright as long as the function remains the same every iteration. https://stackoverflow.com/a/1247490/1453822 – DeepSpace May 26 '17 at 11:43
  • It's not just `lambda`; the `lambda` expression isn't re-evaluted for each object. – chepner May 26 '17 at 12:07
  • Unless you already have a function that accepts the right argument(s), you need to provide a user-defined wrapper function as the first argument of `map`. It's the overhead of calling the wrapper that can make a `map`-based solution slower than an alternative. – chepner May 26 '17 at 12:14