我在尝试检查元素是否是Python中集合的一部分时遇到问题。 (我的集合包含大约600K元组的字符串。)
我正在搜索一个使用in
运算符的优势的解决方案,以检查值是否是该集合元组的元素。
我找到了解决方案:
# S set of tuples, I'm checking if v is the second element of a tuple
any( y == v for (_, y) in S )
但这有O(n)的复杂性。
Python文档说IN运算符的平均复杂度是O(1)。
修改
我的问题是:如何使用in
运算符的速度检查元素是否是该集合中至少一个元组的第一个/第二个...元素。< / p>
答案 0 :(得分:4)
包含测试的复杂性取决于对象类型,而不是运算符,因为操作被委托给容器。列表中的测试包含是O(n),集合中的包含是O(1)。
但是,您没有测试集合中的包含,您正在测试一堆元组中的包含(元组的容器可以帮助)。如果没有进一步处理,你在这里做得比O(n)好。
您可以创建和维护单独的数据结构,例如,跟踪元组中包含的单独值以及元组本身,然后针对这些单独的数据结构进行测试。这会增加内存需求,但会降低计算成本。
您可以在程序的生命周期内分摊保持该结构最新的成本(仅增加构建数据结构的不变成本),作为回报,您可以获得O(1)操作在你的收容测试。只有在需要多次执行此测试时才能执行此操作,以获得不同的值。
答案 1 :(得分:2)
IN运算符的平均复杂度为O(1)
对于成员资格检查集合或任何使用哈希表存储它的项目(如字典)的容器都是正确的。
它完全不同于跟随in
的操作:
for (_, y) in S
in
只是for
循环语法的一部分。
此外,如果您想获取包含特定字符串的元组,您可以使用列表推导而不是any
:
[item for item in S if my_str in item]
如果你想利用set
的会员资格检查,你应该拥有套装而不是元组,但由于它们不能用,你不能被允许使用它们在set
范围内,您可以使用frozenset()
代替any
。
如果您只想检查是否存在符合特定条件的项目,您可以在any(my_str in item for item in S)
中使用以下生成器表达式:
my_str in my_dict
毕竟,因为您的集合完全具有成为字典的潜力,您可以创建字典而不是设置,然后只需使用{'luca': 1, 'mario': 2 , 'franco': 3}
检查成员资格。您的词典将类似于:address = ('', 21)
答案 2 :(得分:0)
回答提出的问题(注意:这不是您通常想要解决的问题,因为它保证O(n)
行为,因为in
运算符没有保证{{} 1}},在这种情况下,永远不会。)
您可以通过映射每个O(1)
的无关值来使用in
运算符。使用C级内置函数,对于足够大的输入,这将比tuple
表达式运行得更快,但差异很小(对于足够大的输入,可能加速10%,其值不是't}有):
any
这是有效的,因为 # At top of file
from future_builtins import map # Only on Py2, to get lazy map
from operator import itemgetter
v in map(itemgetter(1), S)
运算符是针对任意迭代器实现的,类似于in
的延迟检查,一次提取一个值,与any
进行比较,并且短路输出如果它找到了打击。
就像我说的,这是v
;在现实世界中,如果您不止一次进行此测试,您可能只想制作目标的O(n)
并重复使用,或者set
将目标映射到获得dict
检查时,如果需要,可以使用相关值其他答案已经充分涵盖了这一点。