- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我使用字典作为查找表,但我开始怀疑列表是否更适合我的应用程序——我的查找表中的条目数量并没有那么大。我知道列表在底层使用 C 数组,这让我得出结论,在只有几个项目的列表中查找会比在字典中更好(访问数组中的几个元素比计算哈希更快)。
我决定分析替代方案,但结果让我感到惊讶。列表查找仅使用单个元素更好!见下图(log-log plot):
那么问题来了:为什么列表查找的表现如此糟糕?我错过了什么?
在一个附带问题上,引起我注意的另一件事是在大约 1000 个条目之后的 dict 查找时间中出现了一点“不连续性”。我单独绘制了dict查找时间来显示它。
p.s.1 我知道数组和哈希表的 O(n) 与 O(1) 摊销时间,但通常情况下,迭代数组的少量元素比使用一个哈希表。
p.s.2 这是我用来比较字典和列表查找时间的代码:
import timeit
lengths = [2 ** i for i in xrange(15)]
list_time = []
dict_time = []
for l in lengths:
list_time.append(timeit.timeit('%i in d' % (l/2), 'd=range(%i)' % l))
dict_time.append(timeit.timeit('%i in d' % (l/2),
'd=dict.fromkeys(range(%i))' % l))
print l, list_time[-1], dict_time[-1]
p.s.3 使用 Python 2.7.13
最佳答案
I know lists use C arrays under the hood which made me conclude that lookup in a list with just a few items would be better than in a dictionary (accessing a few elements in an array is faster than computing a hash).
当然,访问一些数组元素很便宜,但计算 ==
在 Python 中却出人意料地重量级。看到第二张图中的尖峰了吗?这就是为两个整数计算 ==
的成本。
您的列表查找需要计算 ==
比您的 dict 查找更多。
同时,计算哈希值对于很多对象来说可能是一个相当重量级的操作,但对于这里涉及的所有 int,它们只是对自己进行哈希处理。 (-1 会散列到 -2,大整数(技术上是 long
s)会散列到更小的整数,但这不适用于这里。)
字典查找在 Python 中并没有那么糟糕,尤其是当您的键只是一个连续的整数范围时。这里所有的 int 都自己散列,Python 使用自定义的开放寻址方案而不是链接,所以你所有的键最终在内存中几乎和你使用列表一样连续(也就是说,指向键的指针结束在连续的 PyDictEntry
范围内)。查找过程很快,而且在您的测试用例中,它总是在第一次探测时点击右键。
好的,回到图 2 中的峰值。第二个图中 1024 个条目的查找时间峰值是因为对于所有较小的大小,您要查找的整数都是 <= 256,所以它们都在CPython 的小整数缓存的范围。 Python 的引用实现为从 -5 到 256 的所有整数保留规范整数对象,包括在内。对于这些整数,Python 能够使用快速指针比较来避免经历计算 ==
的(令人惊讶的重量级)过程。对于较大的整数,in
的参数不再是与 dict 中匹配的整数相同的对象,Python 必须经历整个 ==
过程。
关于python - 为什么字典查找总是比列表查找好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43690191/
如标题所示,ans_list是一个答案列表,ans_index是一个数字(答案在词汇表中的索引,但与atm无关) 这里生成的 tree.anslist 是什么? (例如,仅针对第一个),忽略迭代。 f
我目前将用户的输入存储在逗号分隔的列表中,如下所示: Userid | Options 1 | 1,2,5 用户在一个数组形式中勾选一组选项,然后用逗号连接起来 1,2,5 然后 MySQ
我目前将用户的输入存储在逗号分隔的列表中,如下所示: Userid | Options 1 | 1,2,5 用户在一个数组形式中勾选一组选项,然后用逗号连接起来 1,2,5 然后 MySQ
我想知道如何完全展平列表和包含它们的东西。除其他外,我想出了一个解决方案,它可以将具有多个元素的东西滑倒并将它们放回原处,或者在滑倒后将具有一个元素的东西拿走。 这与 How do I “flatte
我想知道如何完全展平列表和包含它们的东西。除其他外,我想出了一个解决方案,它可以将具有多个元素的东西滑倒并将它们放回原处,或者在滑倒后将带有一个元素的东西拿走。 这与 How do I “flatte
这个问题已经有答案了: Convert nested list to 2d array (3 个回答) 已关闭 7 年前。 java中有没有快捷方式可以转换 List> 到 String[][] ?
我在排序时遇到问题 List> 。我创建了一个自定义比较器,在其中编写了对数据进行排序的代码。 public class CustomComparator implements Comparator
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: Java Generics: Cannot cast List to List? 我只是想知道为什么下面的java代
试图想出一个 LINQy 方法来做到这一点,但我什么也没想到。 我有一个对象列表<>,其中包含一个属性,该属性是逗号分隔的字母代码列表: lst[0].codes = "AA,BB,DD" lst[1
假设我有这些任务: points = [] point = (1, 2) 我怎么会这样做: points += point 它工作得很好,并且给了我点 = [1, 2]。但是,如果我这样做: poin
如何在 scala 中将 List[Task[List[Header]]] 类型转换为 Task[List[Header]]。 我有一个方法返回 Task[List[Header]] 并多次调用 do
如何在 Java 中查找二维列表的元素? 我有一个参数为 List> 的函数我想知道如何找到这个列表的行和列。 最佳答案 如果你喜欢 List> obj 然后你就可以像这样访问 obj.get(cur
分配 List到 List工作正常。 分配 List>到 List>不编译。 代码 public class Main { public static void main(String[] a
我正在用 Java 编写一个方法,该方法必须接收并迭代 Serializable 的 List。 有什么区别: public void myMethod(List list) { } 和 public
我看到很多人想用 mvvm 更新网格/列表/树的一部分,但他们不想刷新整个列表。 对于所有遇到此问题的人,我做了以下示例。 希望这对你有用。 最佳答案 这是一个简单的例子。整个代码中最重要的是: Bi
我正在为现有的 C++ 库编写包装器,该库使用列表,其中 T 是自定义结构。我被建议使用 vector 而不是列表,但我试图避免修改库。 为了更好地理解这个场景,我做了一个简单的应用程序,使用一个列表
List list List list 这两种声明有什么区别吗? 谢谢, 最佳答案 是的。 List可以包含所有派生自 Base 的不同事物的混合物. List包含同质项(从某种意义上说,它们必须全部
有人可以尽可能详细地解释以下类型之间的区别吗? List List List 让我更具体一点。我什么时候想使用 // 1 public void CanYouGiveMeAnAnswer(List l
我有一个元组列表,每个元组都是一对列表。所以我的数据看起来像: mylist = [(['foo', 'bar'], ['bar', 'bar']),(['bar', 'bar'],['bar', '
也许是一个时髦的标题,但我遇到了以下问题: 给定一个类型为 (a * b) list 的列表,我想创建一个类型为 (a * b list) list 的新列表。一个例子: 给定列表 let testL
我是一名优秀的程序员,十分优秀!