如何在Python中使用集合来查找列表成员资格?

如何在Python中使用集合来查找列表成员资格?,python,set,Python,Set,鉴于: 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()在这种情况下很有用。但如

鉴于:

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()
在这种情况下很有用。但如何做到这一点呢?这可能吗?还是坚持使用我的原始代码更好?

首先将您的
列表
转换为
设置
,因为这样可以将查找时间从
O(n)
缩短到
O(1)

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
timeit
any()的比较


首先将您的
列表
转换为
设置
,因为这样可以将查找时间从
O(n)
缩短到
O(1)

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
timeit
any()的比较


集合不支持列表,可以将其转换为元组

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 = [['Yes', 'No'], ['Yes', 'Idontknow'], ['No', 'Yes'], ['No', 'Idontknow']]
valid = ('Yes', 'No') in {tuple(item) for item in A}

正如@IgnacioVazquez Abrams提到的,从列表到元组的转换是O(n),因此如果您了解性能,您需要选择其他方法。

如果您想检查是否存在,您可以在一个

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'和i[2]=='No'表示*10000中的i)
实际上似乎比转换本身快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

如果您想检查是否存在,您可以在一个

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'和i[2]=='No'表示*10000中的i)
实际上似乎比转换本身快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

下面是如何使用Set()执行此操作


集合的元素应该是可散列的。。所以我使用元组作为集合元素,而不是列表

下面是如何使用Set()完成此操作


集合的元素应该是可散列的。。所以我使用元组作为集合元素,而不是列表

你想实现什么?为什么你认为集合在这种情况下会有用?另外,else子句可能比sentinel更有效。
set()
不维护任何顺序,从你的代码来看,你似乎依赖于索引位置,这在集合中是不可能的。@gefei我想检查是否存在n[0]=='Yes'和n[1]=='No'。您想实现什么?为什么您认为在这种情况下集合会有用?另外,else子句可能比sentinel更有效。
set()
不维护任何顺序,从你的代码来看,你似乎依赖于索引位置,这在集合中是不可能的。@gefei我想检查是否存在n[0]='Yes'和n[1]='No'。到集合的转换是O(n),因此在建议之前需要进行分析。到集合的转换是O(n),因此,在建议之前需要进行分析。如果您可以编辑您的答案以适合我编辑的问题,这将是一件好事。
s=set(tuple(tuple(tuple([x[0],x[-1]]),对于A中的x))
在我的机器上大约需要
5.6us
,因此,您确实必须进行一些分析,看看这是否加快了速度。@root
set
创建确实是一项繁重的操作,但是考虑到列表是否包含一百万项,那么使用列表进行查找肯定是一个坏主意。
O(n)
如果您在a}中为x形成一个集合
{tuple([x[0],x[-1]])
的速度几乎是垃圾邮件的两倍。很抱歉,但是
%timeit any({(x[0],x[-1])==('Yes','No')对于A*10000}中的x来说,
比转换本身快了两倍:如果你能编辑你的答案以适应我编辑的问题,那就好了。
s=set(tuple(tuple([x[0],x[-1])对于A中的x))
在我的机器上大约需要
5.6us
,因此,您确实必须进行一些分析,看看这是否加快了速度。@root
set
创建确实是一项繁重的操作,但是考虑到列表是否包含一百万项,那么使用列表进行查找肯定是一个坏主意。
O(n)
如果您在a}中为x形成一个集合
{tuple([x[0],x[-1]])
的速度几乎是垃圾邮件的两倍。很抱歉,但是
%timeit any({(x[0],x[-1])==('Yes','No'),对于*10000}中的x)
比转换本身快两倍:P