Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I use list comprehension to count high or low pair?

I am trying to make my code more elegant/less verbose with list comprehension. I have the following so far:

a = [47, 67, 22]
b = [26, 47, 12]

at = 0
bt = 0
    
for a, b in [c for c in zip(a, b)]:
    if a>b:
        at+=1
    elif a<b:
        bt+=1

I’ve been trying to do something like this to remove the if elif statements:

[at+=1 if (a>b) else bt+=1 if (a<b) for a, b in [c for c in zip(a, b)]] 

Which gives me a invalid syntax error highlighting the at+=1 (so I’ve gone down a rabbit hole:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[at+=1 if (a>b) else bt+=1 if (a<b) else hello=None for a, b in [c for c in zip(a, b)]] 
       ^^
SyntaxError: invalid syntax

>Solution :

I’m not sure that list comprehension is more elegant (because it can be harder to read for people new to the language). However, you can write something like:

a = [47, 67, 22]
b = [26, 47, 12]

at = sum(1 for x,y in zip(a,b) if x > y)
bt = sum(1 for x,y in zip(a,b) if x < y)

This uses a generator expression to count all the pairs which are either truly greater or truly smaller.

You are running into syntax errors because the trinary operator (bar if foo else baz) needs all three parts. It also must produce an output, so you can’t use it to filter during a comprehension.

If you wish to filter during a comprehension you need to use the (<expr> for <iterator> if <filter_expr>) variant of a comprehension which will skip elements for which the filter_expr evaluates to false.

Edit: Deceze pointed out that this will iterate over the list twice. This is true and could be fixed by sacrificing readability:

a = [47, 67, 22]
b = [26, 47, 62]  # changed the array for demo purposes

result = sum(1 if x > y else 1j if x < y else 0 for x,y in zip(a,b))
at, bt = int(result.real), int(result.imag)

This solution is, however, specific to this particular example.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading