2

我有一个Python字典列表。列表的每个元素都有一个type带有元素类型的键。像这样的东西:

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]

我想知道列表l中的所有元素是否都相同type

我有这个:

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

假设列表总是相同的大小,是否有更 Pythonic 的方式来做到这一点?

4

3 回答 3

8

进入我脑海的第一件事:

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

类型集的长度:

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

all使用生成器更有效,但不是使用列表:

>>> %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

使用缓存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使用 list-comp 甚至比使用genexpr 更慢:

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

 

set当没有短路的可能性时,我想到了另一种更快的方法:

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

 

另一个编辑:显然最直接的方法是最快的:

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

同类型长输入(无短路)

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

不同类型的长输入(立即短路)

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
于 2013-02-25T18:06:20.030 回答
5

使用 aset()收集所有类型,然后测试它是否为长度 1:

def same_type(L):
    if not L: return True  # empty list case
    return len(set(d['type'] for d in L)) == 1

这必须扫描所有元素。您还可以与第一个元素进行比较此时您只需要进行足够的测试即可找到不匹配的元素:

def same_type(L):
    if not L: return True  # empty list case
    t = L[0]['type']
    return all(t == d['type'] for d in L)

对于较小的输入,该set()方法更快,但对于较大的set()输入,如果输入中存在第二种类型的可能性足够大,则第二种形式可以击败该方法。

于 2013-02-25T18:07:01.657 回答
4

适用于任何长度lst

def same_type(lst):
    return all(d['type'] == lst[0]['type'] for d in lst[1:])

len(set(...)) == 1它相比更快,因为它type会在发现不同时立即停止。

于 2013-02-25T18:06:25.550 回答