Python 查找列表中包含未知值的元组结构
假设我有一个元组列表:Python 查找列表中包含未知值的元组结构,python,list,tuples,Python,List,Tuples,假设我有一个元组列表: list = [(1,5), (1,7), (2,3)] Python中有没有一种方法可以编写类似这样的内容 if (1, *) in list: do things 其中,*表示“我不在乎这个值”?因此,我们正在检查是否有一个元组,第一个位置为1,第二个位置为任意值 据我所知,在其他语言中有特殊的机制,但我只是不知道这个特殊问题的名称。那么Python中是否有类似的行为 我知道我可以在这里使用列表理解法。我只是对这种特殊的机制感兴趣。您可以使用: 如果在元组的第一个
list = [(1,5), (1,7), (2,3)]
Python中有没有一种方法可以编写类似这样的内容
if (1, *) in list: do things
其中,*
表示“我不在乎这个值”?因此,我们正在检查是否有一个元组,第一个位置为1
,第二个位置为任意值
据我所知,在其他语言中有特殊的机制,但我只是不知道这个特殊问题的名称。那么Python中是否有类似的行为
我知道我可以在这里使用列表理解法。我只是对这种特殊的机制感兴趣。您可以使用:
如果在元组的第一个位置发现
1
,这将有效地测试并提前退出。这可以在Python中使用列表理解来完成。
例:
将为您提供:
[(1, 2), (1, 4)]
元组中的元素数也可以处理
>>> import operator
>>> mylist = [(1,2), (1,5), (4,5,8)]
>>> any(i==1 for i in map(operator.itemgetter(0), mylist))
True
并非我下面提供的所有解决方案方法都一定有效。我的目标是展示我能想到的每一种可能的解决方法——在我的答案的末尾,我提供了“基准”结果,以说明为什么或者为什么你不应该使用一种方法而不是另一种方法。我相信这是一种很好的学习方式,我会无耻地在我的回答中鼓励这种学习
子集+散列
set
s
map()
和匿名函数
过滤器
和匿名函数
微基准 条件
- 1000件
- 100K重复
- 0-100随机范围
- Python 2.7.10、IPython 2.3.0
这个故事的寓意是:当其他用户的答案实际上是正确的时,不要花超过10分钟的时间“证明”你的劣质解决方案在一个小测试数据上更快、更高效像你要求的占位符对象本机不受支持,但你可以自己制作这样的东西:
class Any(object):
def __eq__(self, other):
return True
ANYTHING = Any()
lst = [(1,5), (1,7), (2,3)]
\uuuu eq\uuu
方法定义了两个对象如何测试相等性。(有关详细信息,请参阅。)在这里,任何东西
与任何对象的相等性总是测试为阳性。(除非该对象也以返回False的方式覆盖了\uuuu eq\uuu
。)
中的操作符只为列表中的每个元素调用\uuuuuuuuuuuuuuuuuuuuuuuuuuu
。也就是说,b中的a执行类似以下操作:
for elem in b:
if elem == a:
return True
这意味着,如果在lst
中说(1,任意项),Python将首先将(1,任意项)
与lst
中的第一个元素进行比较。(反过来,元组定义\uuuueq\uuuuu
返回True,如果它的所有元素\uuuueq\uuuuuu
返回True。即(x,y)==(a,b)
相当于x==a和y==b
,或者x.\uuuueq\uuuuuuuuuuuu(a)和y.
)
因此,lst中的(1,任意项)将返回True,而lst中的(3,任意项)将返回False
另外,请注意,我将您的列表重命名为lst
,而不是list
,以防止名称与Python内置的list
冲突。听起来您实际上想要的是filter()
,而不是any()
:
该方法非常好,因为您可以直接向其提供函数。这使您可以指定要筛选的某个键等。为了进一步简化它,请使用lambda表达式将整个内容变成一行。索引是最简单的,但是如果您希望使用与示例类似的语法,其中您希望将第一个值赋给一个变量,而忽略其余值,则可以使用python3
或者用任何逻辑:
In [4]: l = [(1,5), (1,7), (2,3)]
In [5]: any(a == 1 for a,*_ in l)
Out[5]: True
或在没有函数调用的情况下模拟任何函数:
In [23]: l = [(1,5), (1,7), (2,3)]
In [24]: g = (a for a,*_ in l)
In [25]: 1 in g
Out[25]: True
In [26]: list(g)
Out[26]: [1, 2]
旁注:不要命名变量列表
。这将与Python标准库中的列表
函数和数据类型冲突。相关:您选择了错误的答案-1@Justin:当然可以,但是在WHERE EXISTS
子句中包装该选择。语言功能的名称是QbE(示例查询)、统一(Prolog)或简单的“模式匹配”。map()
违背了any()
的目的;现在,您创建了一个包含所有布尔结果的列表。这就是为什么通常将生成器表达式与any()
一起使用;你可以直接创建集合,同样使用生成器表达式而不是列表理解。也许请其他人阅读[…]它教会了我不要骄傲,我们都可以从彼此身上学到一两件事。也许除了你。也许你已经是个万事通了。我不知道。无论如何,谢谢你,问问他们这是怎么回事?这一评论并没有得到赞赏。:-)@玛蒂扬皮特斯:哈哈哈,我很抱歉-我实际上是想让你觉得我尊重你的专业知识,就像你已经知道了一切,你是老师的次数比你是学生的次数多。但事后看来,老兄,我听起来确实像个令人难以置信的混蛋(请原谅我的语言)!但不,那是我的错,我不想那样说。我看到你在其他地方帮助别人,我很感激你为社区所做的一切。伙计,我现在感觉有点糟糕。抱歉,我的好人!这种反应值得称赞。我们都需要不时地这样做。先发制人:从技术上讲,在进行涉及重新定义\uuuu eq\uuuu
的欺骗时,还应该重新定义\uu ne\uuuu
,但在这种情况下不需要这样做。另外请注意,ANYTHING==x
将返回True,而不管x
的值如何,但x==ANYTHING
不一定返回True。还有其他一些答案谈到内置的“any”,为什么您认为本机不支持它?@AlokThakur:这里有两个不同的功能,听起来非常相似。确实,本机支持检查iterable的任何元素是否为真,但OP听起来并不是他想知道的。第二个问题更有趣
>>> a_list = [(1,5), (1,7), (2,3)]
>>>
>>> filter(lambda x: x[0] == 1, a_list)
[(1,5), (1,7)]
>>>
>>> len(filter(lambda x: x[0] == 1, a_list)) > 0 # non-empty list
True
from pprint import pprint
from random import randint
from timeit import timeit
N_ITEMS = 1000
N_SIM = 1 * (10 ** 5) # 100K = 100000
a_list = [(randint(0, 100), randint(0, 100)) for _ in range(N_ITEMS)]
set_membership_list_comprehension_time = timeit(
"1 in set([l[0] for l in a_list])",
number = N_SIM,
setup="from __main__ import a_list"
)
bool_membership_map_time = timeit(
"True in set(map(lambda x: x[0] == 1, a_list))",
number = N_SIM,
setup="from __main__ import a_list"
)
nonzero_length_filter_time = timeit(
"len(filter(lambda x: x[0] == 1, a_list)) > 0",
number = N_SIM,
setup="from __main__ import a_list"
)
any_list_comprehension_time = timeit(
"any(t[0] == 1 for t in a_list)",
number = N_SIM,
setup="from __main__ import a_list"
)
results = {
"any(t[0] == 1 for t in a_list)": any_list_comprehension_time,
"len(filter(lambda x: x[0] == 1, a_list)) > 0": nonzero_length_filter_time,
"True in set(map(lambda x: x[0] == 1, a_list))": bool_membership_map_time,
"1 in set([l[0] for l in a_list])": set_membership_list_comprehension_time
}
pprint(
sorted(results.items(), key = lambda x: x[1])
)
[('any(t[0] == 1 for t in a_list)', 2.6685791015625), # winner - Martijn
('1 in set([l[0] for l in a_list])', 4.85234808921814),
('len(filter(lambda x: x[0] == 1, a_list)) > 0', 7.11224889755249),
('True in set(map(lambda x: x[0] == 1, a_list))', 10.343087911605835)]
class Any(object):
def __eq__(self, other):
return True
ANYTHING = Any()
lst = [(1,5), (1,7), (2,3)]
for elem in b:
if elem == a:
return True
tuple_list = [(1,5), (1,7), (2,3)]
for pair in filter(lambda pair: (pair[0] == 1), tuple_list):
print "Second value {pair[1]} found from {pair}".format(pair=pair)
...
Second value 5 found from (1, 5)
Second value 7 found from (1, 7)
In [3]: [a for a,*_ in l]
Out[3]: [1, 1, 2]
In [4]: l = [(1,5), (1,7), (2,3)]
In [5]: any(a == 1 for a,*_ in l)
Out[5]: True
In [23]: l = [(1,5), (1,7), (2,3)]
In [24]: g = (a for a,*_ in l)
In [25]: 1 in g
Out[25]: True
In [26]: list(g)
Out[26]: [1, 2]