在元组python中使用运算符

时间:2017-04-18 10:08:15

标签: python performance set tuples any

我在尝试检查元素是否是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>

3 个答案:

答案 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检查时,如果需要,可以使用相关值其他答案已经充分涵盖了这一点。