-1
l = [1,1,3,3,4,1,1,1,1,1,1,1,1,7000]
elem = 1;

# Terse method to find count of elem
cnt_of_1 = len([i for i in l if i == elem])

# Verbose method to find count of elem
cnt = 0
for i in l:
    if i == elem:
        cnt += 1

Between the two approaches which is a more pythonic code and why? I do realize in the terse approach, python will be internally creating a new list and iterating through the list to find the length of the new list; hence increasing the space complexity to O(n). As opposed to the more verbose code, which has a space complexity O(1) since the only extra space required is the integer cnt variable.

As for readability, I prefer the first approach as it's a single line with a relatively simple logic, hence allowing me to skip the line and maintaining my focus on bigger picture (may be domain or an algorithm related focus).

I would like people's thoughts here.

Dhawan Gayash
  • 463
  • 1
  • 4
  • 17
  • 3
    `sum(1 for i in l if i == elem)`? You don't need to build the list. – jonrsharpe Nov 26 '19 at 21:33
  • 11
    Does it have to be one of those 2 methods? Because `l.count(elem)` will work fine – MoonMist Nov 26 '19 at 21:33
  • @Aggragoth Does `l.count(elem)` have a similar time complexity as the verbose approach? – Dhawan Gayash Nov 26 '19 at 21:36
  • 1
    Possible duplicate of [Fastest way to count number of occurrences in a Python list](https://stackoverflow.com/questions/12452678/fastest-way-to-count-number-of-occurrences-in-a-python-list) and [How can I count the occurrences of a list item?](https://stackoverflow.com/questions/2600191/how-can-i-count-the-occurrences-of-a-list-item) – pault Nov 26 '19 at 21:37
  • 1
    The complexity is the same, but with a smaller constant because it is implemented as part of the `list` type, not at the Python level. – chepner Nov 26 '19 at 21:37
  • this illustrates one of the things I really dislike about python: it has this special ability to draw out some really inefficient solutions to easy problems, in the name of being "pythonic" (not that that is occuring *here*, but the temptation is there...) – Z4-tier Nov 26 '19 at 21:38
  • @pault Thank you for pointing me to this post. It was quite helpful. – Dhawan Gayash Nov 26 '19 at 21:39
  • @Z4-tier You can write wildly inefficient code in any language; I'm not sure why you are singling Python out here. – chepner Nov 26 '19 at 21:40
  • @JourneyMan This might answer your question: https://stackoverflow.com/questions/44812468/what-is-the-time-complexity-of-python-lists-count-function – MoonMist Nov 26 '19 at 21:41
  • 1
    In a quick test, `l.count(elem)` is about 4x faster than the verbose method. – chepner Nov 26 '19 at 21:41
  • @chepner You are right and I agree, but python just seems to have a unique ability to draw it out. I think maybe it a symptom of code golf being confused for efficient code. – Z4-tier Nov 26 '19 at 21:47
  • 1
    @Z4-tier it's definitely something I see all the time. Apparently, it was one of the main arguments for adding an assignment expressions in 3.8, that many people will prefer to write something terse than just saving the result of an expensive calculation to an intermediate variable. I fear though, that the assignment expressions will just open up a new can of crap – juanpa.arrivillaga Nov 26 '19 at 21:58

2 Answers2

0

In this particular case, the most idiomatic way would be to use:

l.count(elem)

Don't roll your own version of built-in list methods, there is little hope of improving it.

In general, a for-loop versus a list comprehension is a matter of taste. I for one hate using an O(N) algorithm when an O(1) algorithm is trivial, so I would never use len([...]). You could do something like:

sum(1 for x in l if x == elem)

But personally, I find that slightly less readable.

I reserve list comprehensions for simple data-transformations, i.e. some combination of a map/filter operation.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
-1

Even terser:

cnt_of_1 = sum(i == elem for i in l)

It works because True == 1 and False == 0.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I don't like this approach as this seems like a very python specific knowledge that not everybody will understand or know. – Dhawan Gayash Nov 26 '19 at 21:42
  • 1
    I don't like this because it's reimplementing a builtin `list` method. The fact that `bool` is a subclass of `int` isn't a particularly obscure bit of knowledge. – chepner Nov 26 '19 at 21:43
  • @chepner to be honest I didn't know about the builtin `list` method. Python is big enough that pieces of it can escape your attention. – Mark Ransom Nov 26 '19 at 21:44
  • 3
    The second comment pointed it out 6 minutes before you posted this answer. – chepner Nov 26 '19 at 21:45
  • @JourneyMan yes it's esoteric knowledge, but it can come in handy when trying to understand other parts of Python. For example, you can't have a dictionary with both `False` and `0` as keys. – Mark Ransom Nov 26 '19 at 21:46
  • 1
    @chepner so it took me 6 minutes to figure out exactly how to phrase my answer - I never saw the comment. I don't consider that a huge failing. – Mark Ransom Nov 26 '19 at 21:48