Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way of comparing multiple elements in a list of dictionaries

Tags:

python

I have a list of dictionaries in Python. Each element of the list has a type key with the element's type. Something like this:

e1 = {"type": 1, "value": 23.1}
e2 = {"type": 1, "value": 21.1}
e3 = {"type": 2, "value": -10.1}
e4 = {"type": 1, "value": -2.59}
l = [e1, e2, e3, e4]

I would like to know if all elements in list l are of the same type.

I have this:

def same_type(l):
    return l[0].type == l[1].type == l[2].type == l[3].type

Assuming list are always going to be the same size, is there a more pythonic way of doing this?

like image 477
Pablo Santa Cruz Avatar asked Jan 17 '26 08:01

Pablo Santa Cruz


1 Answers

First thing that comes into my head:

all(e['type'] == L[0]['type'] for e in L)

The length of set of types:

len(set(e['type'] for e in L)) == 1

is more efficient than all with a generator, but not with a list:

>>> %timeit all(e['type'] == l[0]['type'] for e in l)
1000000 loops, best of 3: 784 ns per loop

>>> %timeit len(set(e['type'] for e in l)) == 1
1000000 loops, best of 3: 676 ns per loop

>>> %timeit all([e['type'] == l[0]['type'] for e in l])
1000000 loops, best of 3: 602 ns per loop

With cached l[0]['type']:

>>> t1 = l[0]['type']
>>> %timeit all([e['type'] == t1 for e in l])
1000000 loops, best of 3: 447 ns per loop

>>> %timeit all(e['type'] == t1 for e in l)
1000000 loops, best of 3: 655 ns per loop

set with a list-comp is even slower then with a genexpr:

>>> %timeit len(set([gettype(e) for e in l])) == 1
1000000 loops, best of 3: 735 ns per loop

 

I thought of another way that's faster then set when there are no possibilities to short-circuit:

>>> %timeit [e['type'] for e in l].count(t1) == len(l)
1000000 loops, best of 3: 421 ns per loop

 

Another edit: apparently the most straightforward method is the fastest:

In [31]: def same_type(L):
   ....:     t1 = L[0]['type']
   ....:     for e in L:
   ....:         if e['type'] != t1:
   ....:             return False
   ....:     return True
   ....:

In [32]: %timeit same_type(l)
1000000 loops, best of 3: 352 ns per loop

Long input with the same type (no short-circuiting)

In [47]: l = [{'type': 1} for _ in range(1000)]

In [48]: %timeit same_type(l)
10000 loops, best of 3: 37.6 us per loop

In [49]: %timeit  all(e['type'] == l[0]['type'] for e in l)
10000 loops, best of 3: 112 us per loop

In [50]: %timeit all([e['type'] == l[0]['type'] for e in l])
10000 loops, best of 3: 103 us per loop

In [51]: %timeit len(set(e['type'] for e in l)) == 1
10000 loops, best of 3: 63.3 us per loop

Long input with different types (short-circuit right away)

In [40]: l = [{'type': x} for x in range(1000)]

In [43]: %timeit same_type(l)
1000000 loops, best of 3: 337 ns per loop

In [44]: %timeit  all(e['type'] == l[0]['type'] for e in l)
1000000 loops, best of 3: 656 ns per loop

In [45]: %timeit all([e['type'] == l[0]['type'] for e in l])
10000 loops, best of 3: 99.4 us per loop

In [46]: %timeit len(set(e['type'] for e in l)) == 1
10000 loops, best of 3: 68.6 us per loop
like image 96
Pavel Anossov Avatar answered Jan 19 '26 20:01

Pavel Anossov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!