簡體   English   中英

Pythonic比較字典列表中的多個元素的方法

[英]Pythonic way of comparing multiple elements in a list of dictionaries

我在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方式這樣做?

首先是我的想法:

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

使用list-comp set比使用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

使用set()收集所有類型,然后測試它是否為長度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()方法。

適用於任何長度的lst

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

len(set(...)) == 1它更快,因為一旦找到不同的type它就會停止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM