# Better way to do this dict comprehesion

Peter Otten __peter__ at web.de
Wed Mar 8 03:20:24 EST 2017

```Sayth Renshaw wrote:

> Hi
>
> I have got this dictionary comprehension and it works but how can I do it
> better?

List comprehensions (that's what you have) are nice, but overused.

> from collections import Counter
>
> def find_it(seq):
>      counts = dict(Counter(seq))

There is no need to convert Counter to dict.

>      a = [(k, v) for k,v in counts.items() if v % 3 == 0]
>      return a[0][0]
>
> test_seq = [20,1,-1,2,-2,3,3,5,5,1,2,4,20,4,-1,-2,5]
>
> so this returns 5 which is great and the point of the problem I was doing.
>
> Can also do it like this
> def find_it(seq):
>      counts = dict(Counter(seq))
>      a = [(k) for k,v in counts.items() if v % 3 == 0]
>      return a[0]
>
> But the given problem states there will always only be one number
> appearing an odd number of times given that is there a neater way to get

If you mean there is only one number satisfying the v % 3 == 0 condition
then there is no need to go through the whole sequence. The clearest way to
express that is

for k, v in counts.items():
if v % 3 == 0:
return k
raise ValueError

but

it = (k for k, v in counts.items() if v % 3 == 0)
try:
return next(it)
except StopIteration:
pass
raise ValueError

is also possible. The parens (...) instead of [...] make "it" generator
expression which is evaluated lazily.

Both alternatives shown above ensure that at least one value satisfies the
condition "number of occurencies divides by three without rest". If you want
to play it safe and verify that there is exactly one such key you may keep
the listcomp, preferably that from your second implementation.

a = [...]
if len(a) != 1:
raise ValueError
return a[0]

or

[result] = a  # will raise a ValueError if len(a) != 1

The complete code:

>>> from collections import Counter
>>> def find_it(seq):
...     [result] = [k for k, v in Counter(seq).items() if v % 3 == 0]
...     return result
...
>>> test_seq = [20,1,-1,2,-2,3,3,5,5,1,2,4,20,4,-1,-2,5]
>>> find_it(test_seq)
5

```