Python集与列表

时间:2010-05-14 00:55:56

标签: python performance list set

在Python中,哪种数据结构更有效/更快?假设顺序对我来说并不重要,无论如何我都会检查重复项,Python设置是否比Python列表慢?

10 个答案:

答案 0 :(得分:188)

这取决于你打算用它做什么。

在确定对象是否存在于集合中时(如在x in s中),集合明显更快,但在迭代其内容时比列表慢。

您可以使用timeit module查看哪种情况更快。

答案 1 :(得分:127)

当您只想迭代这些值时,列表比设置略快。

但是,如果要检查项目中是否包含项目,则

设置明显快于列表。它们只能包含唯一的项目。

事实证明,元组的表现几乎与列表完全相同,除了它们的不变性。

<强>迭代

>>> def iter_test(iterable):
...     for i in iterable:
...         pass
...
>>> from timeit import timeit
>>> timeit(
...     "iter_test(iterable)",
...     setup="from __main__ import iter_test; iterable = set(range(10000))",
...     number=100000)
12.666952133178711
>>> timeit(
...     "iter_test(iterable)",
...     setup="from __main__ import iter_test; iterable = list(range(10000))",
...     number=100000)
9.917098999023438
>>> timeit(
...     "iter_test(iterable)",
...     setup="from __main__ import iter_test; iterable = tuple(range(10000))",
...     number=100000)
9.865639209747314

确定对象是否存在

>>> def in_test(iterable):
...     for i in range(1000):
...         if i in iterable:
...             pass
...
>>> from timeit import timeit
>>> timeit(
...     "in_test(iterable)",
...     setup="from __main__ import in_test; iterable = set(range(1000))",
...     number=10000)
0.5591847896575928
>>> timeit(
...     "in_test(iterable)",
...     setup="from __main__ import in_test; iterable = list(range(1000))",
...     number=10000)
50.18339991569519
>>> timeit(
...     "in_test(iterable)",
...     setup="from __main__ import in_test; iterable = tuple(range(1000))",
...     number=10000)
51.597304821014404

答案 2 :(得分:7)

列出表现:

>>> import timeit
>>> timeit.timeit(stmt='10**6 in a', setup='a = range(10**6)', number=100000)
0.008128150348026608

设定表现:

>>> timeit.timeit(stmt='10**6 in a', setup='a = set(range(10**6))', number=100000)
0.005674857488571661

您可能需要考虑元组,因为它们与列表类似,但无法修改。它们占用的内存略少,访问速度更快。它们不像列表那样灵活,但效率更高。它们的正常用途是作为字典键。

集也是序列结构,但与列表和元组有两个不同之处。虽然集合确实有订单,但该顺序是任意的,不受程序员的控制。第二个区别是集合中的元素必须是唯一的。

根据定义,

set。 [python | wiki]。

>>> x = set([1, 1, 2, 2, 3, 3])
>>> x
{1, 2, 3}

答案 3 :(得分:3)

Set因近乎即时的“包含”检查而获胜:https://en.wikipedia.org/wiki/Hash_table

列表实现:通常是一个数组,接近金属的低级别,适合迭代和元素索引的随机访问。

设置实现:https://en.wikipedia.org/wiki/Hash_table,它不会在列表上进行迭代,但会通过从键计算哈希来找到该元素,因此它依赖于关键元素和哈希函数的本质。与用于词典的内容类似。我怀疑list如果你的元素很少(&lt; 5)可能会更快,元素数越多,set对包含检查的效果越好。元素添加和删除也很快。

注意:如果list已经排序,则搜索list可能会非常快,但对于通常的情况,set更快更简单包含支票。

答案 4 :(得分:0)

我建议使用Set实现,其中用例限制引用或搜索存在和Tuple实现,其中用例要求您执行迭代。列表是低级实现,需要大量内存开销。

答案 5 :(得分:0)

tl; dr

数据结构(DS)很重要,因为它们用于对数据执行操作,这些操作基本上意味着:获取一些输入处理回馈输出

在某些特定情况下,某些数据结构比其他数据结构更有用。因此,询问哪个(DS)更有效/更快是相当不公平的。这就像问刀和叉之间哪种工具更有效。我的意思是所有情况都取决于情况。

Lists

列表是可变序列通常用于存储同类项目的集合

Sets

集合对象是不同的可哈希对象的无序集合。它通常用于测试成员资格,从序列中删除重复项以及计算相交,并集,差和对称差等数学运算。

用法

从某些答案中可以明显看出,迭代值时列表比集合快得多。另一方面,检查项目是否包含列表时,集合比列表快。因此,您唯一能说的是,对于某些特定操作,列表比集合要好,反之亦然。

答案 6 :(得分:0)

from datetime import datetime
listA = range(10000000)
setA = set(listA)
tupA = tuple(listA)
#Source Code

def calc(data, type):
start = datetime.now()
if data in type:
print ""
end = datetime.now()
print end-start

calc(9999, listA)
calc(9999, tupA)
calc(9999, setA)

在比较所有3的10次迭代后的输出: Comparison

答案 7 :(得分:0)

使用CPython检查值是否为少量文字之一时,我对结果感兴趣。 set在Python 3 vs tuplelistor中获胜:

from timeit import timeit

def in_test1():
  for i in range(1000):
    if i in (314, 628):
      pass

def in_test2():
  for i in range(1000):
    if i in [314, 628]:
      pass

def in_test3():
  for i in range(1000):
    if i in {314, 628}:
      pass

def in_test4():
  for i in range(1000):
    if i == 314 or i == 628:
      pass

print("tuple")
print(timeit("in_test1()", setup="from __main__ import in_test1", number=100000))
print("list")
print(timeit("in_test2()", setup="from __main__ import in_test2", number=100000))
print("set")
print(timeit("in_test3()", setup="from __main__ import in_test3", number=100000))
print("or")
print(timeit("in_test4()", setup="from __main__ import in_test4", number=100000))

输出:

tuple
4.735646052286029
list
4.7308746771886945
set
3.5755991376936436
or
4.687681658193469

对于3到5个字面量,set仍然大获全胜,而or则是最慢的。

在Python 2中,set始终是最慢的。 or是2到3个文字的最快速度,而tuplelist在4个或更多文字的情况下更快。我无法区分tuplelist的速度。

当将要测试的值缓存到函数之外的全局变量中时,而不是在循环中创建文字,则set每次都赢了,即使在Python 2中也是如此。

这些结果适用于Core i7上的64位CPython。

答案 8 :(得分:0)

集合更快,而且您可以通过集合获得更多功能,比如说您有两个集合:

set1 = {"Harry Potter", "James Bond", "Iron Man"}
set2 = {"Captain America", "Black Widow", "Hulk", "Harry Potter", "James Bond"}

我们可以轻松地加入两组:

set3 = set1.union(set2)

找出两者的共同点:

set3 = set1.intersection(set2)

找出两者的不同之处:

set3 = set1.difference(set2)

还有更多!只是尝试一下,它们很有趣!而且,如果您必须处理2个列表中的不同值或2个列表中的公用值,我更喜欢将列表转换为集合,许多程序员都采用这种方式。 希望它对您有帮助:-)

答案 9 :(得分:0)

@Ellis Percival's tests 一样,我想补充一点,在添加元素时,列表的执行方式与集合类似。

添加元素

>>> def add_test_set(iterable):
...     for i in range(10000):
...         iterable.add(i)
...
>>> def add_test_list(iterable):
...     for i in range(10000):
...         iterable.append(i)
...
>>> timeit("add_test_set(iterable)",
...     setup="from __main__ import add_test_set; iterable = set()",
...     number=10000)
7.073143866999999
>>> timeit("add_test_list(iterable)",
...     setup="from __main__ import add_test_list; iterable = list()",
...     number=10000)
6.80650725000001

(我会编辑他的帖子以包含此内容,但编辑队列已满)