如何使用 d.items() 更改 for 循环中的所有字典键?

2024-01-29

我需要一些帮助来理解为什么这段代码没有按预期工作。

如果想更改字典的键但保留值,他/她可以使用:

d[new_key] = d.pop[old_key]

我想修改所有键(并将值保留在适当的位置),但下面的代码会跳过某些行 - (“col2”)保持不变。是因为字典是无序的并且我不断更改其中的值吗?

我将如何在不创建新字典的情况下更改键并保留值?

import time
import pprint

name_dict = {"col1": 973, "col2": "1452 29th Street",
             "col3": "Here is a value", "col4" : "Here is another value",
             "col5" : "NULL", "col6": "Scottsdale",
             "col7": "N/A", "col8" : "41.5946922",
             "col9": "Building", "col10" : "Commercial"}


for k, v in name_dict.items():
    print("This is the key: '%s' and this is the value '%s'\n" % (k, v) )
    new_key = input("Please enter a new key: ")
    name_dict[new_key] = name_dict.pop(k)
    time.sleep(4)

pprint.pprint(name_dict)

更改正在迭代的对象从来都不是一个好主意。通常情况下dict当您尝试时甚至会抛出异常:

name_dict = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6}

for k, v in name_dict.items():
    name_dict.pop(k)

RuntimeError:字典在迭代期间更改了大小

但是,在您的情况下,您为每个删除的项目添加一个项目。这使得事情变得更加复杂。要理解发生了什么,您需要知道字典有点像稀疏表。例如像这样的字典{1: 1, 3: 3, 5: 5}可能看起来像这样(这在 Python 3.6 中发生了变化,对于 3.6 及更高版本,以下内容不再正确):

hash    key    value
   -      -        - 
   1      1        1
   -      -        - 
   3      3        3
   -      -        - 
   5      5        5
   -      -        - 
   -      -        - 
   -      -        - 

这也是迭代的顺序。因此,在第一次迭代中,它将转到第二项(其中1: 1被储存了)。假设您将密钥更改为2并拔掉钥匙1该字典看起来像这样:

hash    key    value
   -      -        - 
   -      -        - 
   2      2        1
   3      3        3
   -      -        - 
   5      5        5
   -      -        - 
   -      -        - 
   -      -        - 

但我们仍然在第二行,所以下一次迭代它将转到下一个“非空”条目,即2: 1。哎呀...

使用字符串作为键会更加复杂,因为字符串哈希是随机的(基于每个会话),因此字典内的顺序是不可预测的。

在 3.6 中,内部布局发生了一些变化,但这里发生了类似的情况。

假设你有这个循环:

name_dict = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6}

for k, v in name_dict.items():
    # print(k, k+6, name_dict.__sizeof__())
    name_dict[k+6] = name_dict.pop(k)
    # print(name_dict)

最初的布局是这样的:

key   value
  1       1
  2       2
  3       3
  4       4
  5       5
  6       1

第一个循环删除1但补充说7。因为字典在 3.6 中是排序的,所以会在其中插入一个占位符1曾经是:

key   value
  -       -
  2       2
  3       3
  4       4
  5       5
  6       1
  7       2

这会一直持续到您更换为止4 with 10.

key   value
  -       -
  -       -
  -       -
  -       -
  5       5
  6       1
  7       2
  8       3
  9       4
 10       5

但是当你更换5 with 11字典需要增加它的大小。然后发生了一些特别的事情:占位符被删除:

key   value
  6       6
  7       1
  8       2
  9       3
 10       4
 11       5

所以,我们在上次迭代中处于位置 5,现在我们更改第 6 行。但是第 6 行包含11: 5现在。哎呀...

切勿更改要迭代的对象:迭代期间不要弄乱键(值没问题)!

您可以保留一个“翻译表”(不知道这是否违反您的“不创建新字典”要求,但您需要某种存储来使代码正常工作)并在循环后进行重命名:

translate = {}
for k, v in name_dict.items():
    print("This is the key: '%s' and this is the value '%s'\n" % (k, v) )
    new_key = input("Please enter a new key: ")
    translate[k] = new_key
    time.sleep(4)

for old, new in translate.items():
    name_dict[new] = name_dict.pop(old)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 d.items() 更改 for 循环中的所有字典键? 的相关文章

随机推荐