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:
[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.