如何用d.items()更改for循环中的所有字典键? [英] How to change all the dictionary keys in a for loop with d.items()?

查看:525
本文介绍了如何用d.items()更改for循环中的所有字典键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



如果您想更改字典的关键字但保留该值,那么他/她可能会用:

  d [new_key] = d.pop [old_key] 

我想修改所有的键(并保留值),但下面的代码跳过某些行 - (col2)保持不变。是因为字典是无序的,我不断改变它的价值?

我将如何去改变键和保留值,而不创建一个新的字典? p>

 导入时间
导入pprint

name_dict = {col1:973,col2 :1452 29th Street,
col3:这是一个值,col4:这是另一个值,
col5:NULL,col6: Scottsdale,
col7:N / A,col8:41.5946922,
col9:Building,col10:Commercial}
$ ():
print(这是关键:'%s',这是'%s'' ,v))
new_key = input(请输入一个新的键:)
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和更新的版本, )

 哈希键值
- - -
1 1 1
- - -
3 3 3
- - -
5 5 5
- - -
- - -
- - -

这也是迭代的顺序。所以在第一次迭代中,它将转到第二项(存储 1:1 )。让我们假设你将键改为 2 ,并删除键 1 字典看起来像这样:

 哈希键值
- - -
- - -
2 2 1
3 3 3
- - -
5 5 5
- - -
- - -
- - -

但是我们仍然在第二行,所以下一个迭代将进入下一个非空条目,它是 2 :1 。 Oups ...
$ b

字符串作为键更复杂,因为字符串散列是随机的(按每个会话),所以字典内部的顺序是不可预知的。 p>

在3.6版本中,内部布局有所改变,但是在这里发生了类似的情况。



假设你有这个循环: / p>

  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)

初始布局如下所示:

 键值
1 1
2 2
3 3
4 4
5 5
6 1

第一个循环移除 1 ,但添加 7 。因为字典是在3.6中定义的,所以插入一个占位符,其中 1 已经被占据:

 键值
- -
2 2
3 3
4 4
5 5
6 1
7 2

直到您用<$ c $替换 4 c> 10

 键值
- -
- -
- -
- -
5 5
6 1
7 2
8 3
9 4
10 5

但是当用 5 > 11 字典将需要增加它的大小。然后会发生一些特殊情况:占位符被删除:

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

所以,我们在最后一次迭代中的位置5,现在我们改变了第6行。但是第6行现在包含 11:5 。 Oups ...

永远不要改变迭代的对象:不要在迭代过程中乱用键(值可以)!$ / b
$ b

你可以保留一个翻译表(不知道是否违反了你的没有创建一个新的字典的要求,但你需要一些存储,使您的代码正常工作)和在循环之后重命名:

  translate = {} 
for k,v in name_dict.items():
print(这是关键:'%s',这是'%s'\\\
'%(k,v))
的值new_key = input(请输入一个新的密钥:)
translate [k] = new_key
time.sleep(4)

for translate.items()中的旧的,新的:
name_dict [new] = name_dict.pop(旧)


I would like some help with understanding why this code is not working as expected.

If one wants to change the key of a dictionary but keep the value, he/she might use:

d[new_key] = d.pop[old_key]

I want to modify all the keys (and keep the values in place) but the code below skips certain lines - ("col2") remains untouched. Is it because dictionaries are unordered and I keep changing the values in it?

How would I go about changing the keys and keep the values without creating a new dictionary?

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)

解决方案

It's never a good idea to change the object you're iterating over. Normally dict even throws an exception when you attempt it:

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: dictionary changed size during iteration

However in your case you add one item for every removed item. That makes it more convolved. To understand what's happening you need to know that a dictionary is somewhat like a sparse table. For example a dictionary like {1: 1, 3: 3, 5: 5} could look like this (this changed in Python 3.6, for 3.6 and newer the following isn't correct anymore):

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

That's also the order in which it is iterated. So in the first iteration it will go to the second item (where the 1: 1 is stored). Let's assume you change the key to 2 and remove the key 1 the dict would look like this:

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

But we're still at the second line, so the next iteration it will go to the next "not-empty" entry which is 2: 1. Oups ...

It's even more complicated with strings as keys because string hashes are randomized (on a per session basis) so the order inside the dictionary is unpredictable.

In 3.6 the internal layout was changed a bit but something similar happens here.

Assuming you have this loop:

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)

The initial layout is like this:

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

The first loop removes 1 but adds 7. Because dictionaries are ordered in 3.6 this inserts a placeholder where 1 had been:

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

This goes on until you replace 4 with 10.

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

But when you replace 5 with 11 the dictionary will need to increase it's size. Then something special happens: The placeholders are removed:

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

So, we were at position 5 in the last iteration and now we change line 6. But line 6 contains 11: 5 right now. Oups...

Never change the object you're iterating over: Don't mess with the keys during iteration (values are okay)!

You could instead keep a "translation table" (don't know if that violates your "without creating a new dict" requirement but you need some kind of storage to make your code work correctly) and do the renaming after the loop:

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)

这篇关于如何用d.items()更改for循环中的所有字典键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆