问题描述
如果您想更改字典的关键字但保留该值,那么他/她可能会用:
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)
然而,在您的情况下,您为每个移除的项目添加一个项目。这使得它更加卷入。要了解发生了什么,你需要知道字典有点像一个稀疏的表。例如像 {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)
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循环中的所有字典键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!