【问题标题】:python dictionaries when keys are numbers [duplicate]键是数字时的python字典[重复]
【发布时间】:2015-05-29 14:28:32
【问题描述】:

当键是数字时,我对 python 中的字典属性有疑问。 在我的情况下,当我打印带有数字键的字典时,打印的结果将按键排序,但在另一种情况下(键是字符串)字典是无序的。我想知道字典中的这条规则。

l = {"one" : "1", "two" : "2", "three" : "3"}

print(l)

l = {1: "one", 2: "two", 3: "three", 4: "four", 5: "five"}

print(l)

l = {2: "two", 3: "three", 4: "four", 1: "one", 5: "five"}

print(l)

结果:

{'three': '3', 'two': '2', 'one': '1'}

{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}

{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}

【问题讨论】:

  • Python 字典本质上是未排序的。你不能指望他们的订单,它不会被保留。
  • 整数键字典以相同顺序出现的原因可能与 Python 缓存小数字的方式有关。打印此字典{500000: 'five', 400000: 'four', 30000: 'three', 200000000: 'two', 10: 'one'},您会看到不再保留数字顺序。
  • 谢谢,我知道了

标签: python-3.x dictionary numbers key


【解决方案1】:

Python 使用hash table 来存储字典,因此字典或其他使用散列函数的对象中没有排序。

但是关于哈希对象中项目的索引,python根据以下代码within hashtable.c计算索引:

key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);

因此,由于整数的哈希值是整数本身,因此索引基于数字(ht->num_buckets - 1 是一个常数),因此按位计算的索引 - 并且介于 (ht->num_buckets - 1) 和数字之间。

考虑以下使用哈希表的set 示例:

>>> set([0,1919,2000,3,45,33,333,5])
set([0, 33, 3, 5, 45, 333, 2000, 1919])

对于号码33,我们有:

33 & (ht->num_buckets - 1) = 1

其实是这样的:

'0b100001' & '0b111'= '0b1' # 1 the index of 33

注意在这种情况下,(ht->num_buckets - 1)8-1=70b111

对于1919

'0b11101111111' & '0b111' = '0b111' # 7 the index of 1919

对于333

'0b101001101' & '0b111' = '0b101' # 5 the index of 333

有关 python 哈希函数的更多详细信息,请阅读python source code 中的以下引用:

前面的主要细节:大多数哈希方案都依赖于“好的”哈希 函数,在模拟随机性的意义上。 Python 没有:它最 重要的散列函数(用于字符串和整数)非常有规律 案例:

>>> map(hash, (0, 1, 2, 3))
  [0, 1, 2, 3]
>>> map(hash, ("namea", "nameb", "namec", "named"))
  [-1658398457, -1658398460, -1658398459, -1658398462]

这不一定是坏事!相反,在大小为 2**i 的表中,取 作为初始表索引的低阶 i 位非常快,并且有 对于由连续范围的整数索引的字典根本没有冲突。 当键是“连续的”字符串时,情况大致相同。所以这 在常见情况下提供优于随机的行为,这是非常可取的。

OTOH,当发生碰撞时,填充连续切片的趋势 哈希表使良好的冲突解决策略变得至关重要。只取 哈希码的最后 i 位也容易受到攻击:例如,考虑 列表[i << 16 for i in range(20000)] 作为一组键。 由于整数是它们自己的哈希码,并且它适合大小为 2**15 的字典,因此每个哈希码的最后 15 位都是 0:它们映射到同一个表索引。

但迎合不寻常的情况不应该减慢通常的情况,所以我们只是采取 最后我位反正。剩下的工作由碰撞解决来完成。如果 我们通常在第一次尝试时就找到了我们正在寻找的密钥(然后,它变成 出来,我们通常这样做——表加载因子保持在 2/3 以下,所以赔率 完全有利于我们),那么最好保留初始索引 计算非常便宜。

【讨论】:

  • tnx,你的答案很完美;)
  • @FarazMolaee 欢迎,我一直在寻找来源以添加更多解释,但听起来很扭曲!!!!
  • @FarazMolaee 检查编辑!
猜你喜欢
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 2014-09-02
相关资源
最近更新 更多