列表查找性能 - 返回列表的最后一个元素是否必须扫描整个列表?

时间:2013-04-24 18:56:08

标签: python list

假设我有一本字典:

myDict = {
    'title': 'a nice title',
    'nice_list': [1,2,3,4,5,6,6,7,...,99999],
    'nice_lists_last_item': 99999,
}

如果项目大于最终项目,我只想将项目附加到nice_list

什么更快:

  1. 使用:if new_element > nice_list[-1]
    1. 使用:if new_element > nice_lists_last_item
    2. 方法1是否必须扫描整个列表(和/或每次将所有nice_list放入内存中)才能找到该项目?哪个更快? (记住我打算进行几十亿次比较?)

      方法2会将最后一个元素存储为自己独特的dict条目,那么更快吗?

3 个答案:

答案 0 :(得分:6)

如有疑问,请测试:

>>> %timeit if 1 > myDict['nice_list'][-1]: 0
10000000 loops, best of 3: 110 ns per loop
>>> %timeit if 1 > myDict['nice_lists_last_item']: 0
10000000 loops, best of 3: 68.8 ns per loop
>>> nice_list = myDict['nice_list']
>>> %timeit if 1 > nice_list[-1]: 0
10000000 loops, best of 3: 62.6 ns per loop
>>> nice_lists_last_item = myDict['nice_lists_last_item']
>>> %timeit if 1 > nice_lists_last_item: 0                      
10000000 loops, best of 3: 43.4 ns per loop

如您所见,直接访问字典值比从字典访问列表然后访问其最后一个值更快。但是直接访问列表的最后一个值会更快。这应该不足为奇; Python列表知道它们自己的长度,并在内存中实现为数组,因此查找最后一项就像从长度中减去1并进行指针算术一样简单。由于碰撞检测的开销,访问字典键有点慢;但它只会慢几纳秒。最后,如果你真的想节省几纳秒,你可以将最后一个值存储在它自己的值中。

最大的减速来自两者

答案 1 :(得分:4)

从列表中获取项目是O(1),如上所述here。即便如此,显式存储值仍然会更快,因为无论查找速度有多快,它仍然会比不执行查找更慢。 (但是,如果您明确存储该值,则在向列表中添加新项时必须更新它;如果更新它并检查它的合并成本是否超过每次抓取最后一项的成本是您必须自己进行基准测试;这可能取决于您最终实际添加新项目的频率。)

请注意,不存在“将nice_list全部放入内存”的问题。如果你有一个带有列表的dict,那整个列表已经在内存中了。查找其中的值不会导致它占用更多的内存,但是如果你有数十亿的这些列表,你甚至会在尝试查找任何内容之前耗尽内存,因为只是创建列表会耗尽太多的记忆。

答案 2 :(得分:0)

在CPython中,答案可能是否定的。 list是使用动态数组实现的。