[英]How to use sets in Python to find list membership?
鑒於:
A = [['Yes', 'lala', 'No'], ['Yes', 'lala', 'Idontknow'], ['No', 'lala', 'Yes'], ['No', 'lala', 'Idontknow']]
我想知道A中是否存在['Yes', X, 'No']
,其中X
是我不在乎的任何內容。
我嘗試過:
valid = False
for n in A:
if n[0] == 'Yes' and n[2] == 'No':
valid = True
我知道set()
在這種情況下很有用。 但是,這怎么辦呢? 這可能嗎? 還是堅持使用原始代碼更好?
如果您要檢查是否存在,可以['Yes', 'No'] in A
:
In [1]: A = [['Yes', 'No'], ['Yes', 'Idontknow'], ['No', 'Yes'], ['No', 'Idontknow']]
In [2]: ['Yes', 'No'] in A
Out[2]: True
對於下一種情況,請嘗試:
In [3]: A = [['Yes', 'lala', 'No'], ['Yes', 'lala', 'Idontknow'], ['No', 'lala', 'Yes'], ['No', 'lala', 'Idontknow']]
In [4]: any(i[0]=='Yes' and i[2] == 'No' for i in A)
Out[4]: True
或者您可以定義一些功能:
In [5]: def want_to_know(l,item):
...: for i in l:
...: if i[0] == item[0] and i[2] == item[2]:
...: return True
...: return False
In [6]: want_to_know(A,['Yes', 'xxx', 'No'])
Out[6]: True
any(i[0]=='Yes' and i[2] == 'No' for i in A*10000)
實際上比轉換本身快10倍。
In [8]: %timeit any({(x[0],x[-1]) == ('Yes','No') for x in A*10000})
100 loops, best of 3: 14 ms per loop
In [9]: % timeit {tuple([x[0],x[-1]]) for x in A*10000}
10 loops, best of 3: 33.4 ms per loop
In [10]: %timeit any(i[0]=='Yes' and i[2] == 'No' for i in A*10000)
1000 loops, best of 3: 334 us per loop
將您的list
轉換為set
,因為它可以將查找時間從O(n)
縮短為O(1)
:
In [27]: A = [['Yes', 'No'], ['Yes', 'Idontknow'], ['No', 'Yes'], ['No', 'Idontknow']]
In [28]: s=set(tuple(map(tuple,A)))
In [29]: s
Out[29]: set([('Yes', 'No'), ('No', 'Idontknow'), ('Yes', 'Idontknow'), ('No', 'Yes')])
In [30]: ('Yes', 'No') in s
Out[30]: True
timeit
比較:
%timeit ['Yes', 'No'] in A
1000000 loops, best of 3: 504 ns per loop
%timeit ('Yes', 'No') in s
1000000 loops, best of 3: 442 ns per loop #winner
%timeit ['No', 'Idontknow'] in A
1000000 loops, best of 3: 861 ns per loop
%timeit ('No', 'Idontknow') in s
1000000 loops, best of 3: 461 ns per loop #winner
編輯:
如果您只對第一個和最后一個元素感興趣:
In [69]: A = [['Yes', 'No'], ['Yes', 'Idontknow','hmmm'], ['No', 'Yes'], ['No', 'Idontknow']]
In [70]: s={tuple([x[0],x[-1]]) for x in A} # -1 or 2, change as per your requirement
#or set(tuple([x[0],x[-1]]) for x in A)
In [71]: s
Out[71]: set([('Yes', 'No'), ('Yes', 'hmmm'), ('No', 'Idontknow'), ('No', 'Yes')])
In [73]: ('Yes', 'hmmm') in s
Out[73]: True
與any()
timeit
比較:
In [77]: %timeit ('Yes', 'hmmm') in s
1000000 loops, best of 3: 428 ns per loop #winner
In [78]: %timeit any(x[0]=="Yes" and x[-1]=="hmmm" for x in A)
100000 loops, best of 3: 2.87 us per loop
Set不支持列表,您可以將其轉換為元組,
A = [['Yes', 'No'], ['Yes', 'Idontknow'], ['No', 'Yes'], ['No', 'Idontknow']]
valid = ('Yes', 'No') in {tuple(item) for item in A}
如@ IgnacioVazquez-Abrams所述,從列表到元組的轉換為O(n),因此,如果您了解性能,則需要選擇其他方法。
以下是使用Set()的方法。
>>> A = Set([('Yes', 'No'), ('Yes', 'Idontknow'), ('No', 'Yes'), ('No', 'Idontknow')])
>>> ('Yes','No') in A
True
>>>
Set的元素應該是可哈希的..因此,我將元組用作Set元素而不是列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.