Python集与列表

Man*_*tis 168 python performance list set data-structures

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

Mic*_*yan 207

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

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

您可以使用timeit模块查看哪种情况更快.

  • 集合和列表都具有线性时间迭代.说一个人比另一个人"慢"是误导的,并且让那些阅读这个答案的新程序员感到困惑. (23认同)
  • 要回答“就你的观点而言:“集合明显更快”,使其更快的底层实现是什么?” 集合使用哈希函数来确定元素是否在其中(如果哈希函数好,即冲突不常见,复杂度为 O(1)),而确定元素是否在列表中,则通过列表进行迭代必要的(O(n) 复杂度)。[查看 Python 默认数据结构上方法的时间复杂度](https://wiki.python.org/moin/TimeComplexity)。 (6认同)
  • 在迭代时,Set不比列表慢得多. (4认同)
  • 对于您的观点:"集合明显更快",什么是使其更快的底层实现? (3认同)
  • 迭代时它们的运行[时间复杂度](https://en.wikipedia.org/wiki/Time_complexity)均为 O(n),但[平均情况复杂度](https://en.wikipedia.org /wiki/Average-case_complexity) 迭代集比迭代列表大(慢)[~28%](/sf/answers/1256150661/) (2认同)

Ell*_*val 141

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

但是,如果要检查项目是否包含在内,则集合明显快于列表.但它们只能包含唯一的项目.

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

迭代

>>> 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
Run Code Online (Sandbox Code Playgroud)

确定对象是否存在

>>> 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
Run Code Online (Sandbox Code Playgroud)

  • 我发现(初始化集 - > 5.5300979614257812)(初始化列表 - > 1.8846848011016846)(初始化元组 - > 1.8730108737945557)我的intel核心i5四核上带有12GB RAM的大小为10,000的项目.这也应该考虑在内. (4认同)
  • 我已经更新了代码以立即删除对象.timeit循环的设置阶段仅调用一次(https://docs.python.org/2/library/timeit.html#timeit.Timer.timeit). (4认同)

Chr*_*ssy 12

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

列表实现:通常是一个数组,低级接近金属,有利于通过元素索引进行迭代和随机访问

设置实现:https : //en.wikipedia.org/wiki/Hash_table,它不迭代列表,而是通过从键计算散列来找到元素,因此它取决于键元素和散列的性质功能。类似于用于 dict 的内容。我怀疑list如果元素很少(< 5)可能会更快,元素数量越大,set包含检查的性能越好。元素添加和删除也很快。还要记住,建立一个集合是有成本的!

注意:如果list已经排序,则list在小列表上搜索可能会非常快,但是set对于包含检查的数据越多,速度越快。

  • 接近金属?在 Python 的上下文中,这甚至意味着什么?列表如何比集合更接近金属? (10认同)
  • “如果‘列表’已经排序,那么在小列表上搜索‘列表’可能会相当快,但对于更多数据,‘集合’的包含检查速度更快。” 为了避免混淆,您可能应该明确指出,只有当您利用诸如“bisect”模块之类的排序顺序时,排序才会有帮助;无论是否排序,对“list”进行简单的“in”检查都是“O(n)”,而对“set”进行“in”检查是“O(1)”。“bisect”模块可以在预先排序的“list”上将测试降低到“O(log n)”,但使用起来比简单的“in”检查更复杂。 (3认同)
  • @roganjosh,python仍然在机器上运行,并且一些实现(例如 list as 'array')更接近硬件所擅长的:/sf/ask/12320801/使用,但它始终取决于您想要实现的目标,最好了解一些实现,而不仅仅是抽象。 (2认同)

lmi*_*asf 9

太长了;博士

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

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

列表

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

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

用法

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


use*_*995 7

清单表现:

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

设定表现:

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

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

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

set根据定义.[ python | 维基 ].

>>> x = set([1, 1, 2, 2, 3, 3])
>>> x
{1, 2, 3}
Run Code Online (Sandbox Code Playgroud)

  • `range`不是`list`.`range`是一个带有自定义`__contains__`魔术方法的特殊类. (6认同)
  • 首先,您应该更新到`set`内置类型链接(http://docs.python.org/2/lrary/stdtypes.html#set)而不是已弃用的`sets`库.其次,"集合也是序列结构",从内置类型链接中读取以下内容:"作为无序集合,集合不记录元素位置或插入顺序.因此,集合不支持索引,切片或其他序列式的行为." (4认同)

Ped*_*eno 7

在使用 CPython 检查某个值是否是少数文字之一时,我对结果很感兴趣。set在 Python 3 vs 中获胜tuplelist并且or

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))
Run Code Online (Sandbox Code Playgroud)

输出:

tuple
4.735646052286029
list
4.7308746771886945
set
3.5755991376936436
or
4.687681658193469
Run Code Online (Sandbox Code Playgroud)

对于 3 到 5 个字面量,set仍然以较大优势获胜,并且or成为最慢的。

在 Python 2 中,set总是最慢的。or是最快的2至3文本和tuplelist是具有4个或多个文字更快。我无法区分tuplevs的速度list

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

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