将键值对插入字典中的指定位置

Dee*_*App 2 python dictionary yaml

如何在从YAML文档加载的python字典的指​​定位置插入键值对?

例如,如果字典是:

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

我想插入元素 'Phone':'1234'

年龄之前姓名之后。这只是一个例子。我要处理的实际字典很大(已解析的YAML文件),因此删除和重新插入可能会比较麻烦(我不太了解)。

如果我可以在OrderedDict中插入指定位置,那也可以。

ai2*_*2ys 14

遇到了同样的问题并按照如下所述解决了这个问题,不需要任何额外的导入,并且只需要几行代码。使用 Python 3.6.9 进行测试。

  1. 获取键“Age”的位置,因为新的键值对应先插入
  2. 获取字典作为键值对列表
  3. 在特定位置插入新的键值对
  4. 从键值对列表创建字典
mydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
print(mydict)
# {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

pos = list(mydict.keys()).index('Age')
items = list(mydict.items())
items.insert(pos, ('Phone', '123-456-7890'))
mydict = dict(items)

print(mydict)
# {'Name': 'Zara', 'Phone': '123-456-7890', 'Age': 7, 'Class': 'First'}
Run Code Online (Sandbox Code Playgroud)

编辑2021-12-20:
刚刚看到有一个插入方法可用ruamel.yaml,请参阅项目页面中的示例:

import sys
from ruamel.yaml import YAML

yaml_str = """\
first_name: Art
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""

yaml = YAML()
data = yaml.load(yaml_str)
data.insert(1, 'last name', 'Vandelay', comment="new key")
yaml.dump(data, sys.stdout)

Run Code Online (Sandbox Code Playgroud)

  • 对于其他上下文,由于 ruamel.yaml.YAML.load() 返回 `any` 使得 VSCode 无法在没有类型声明的情况下找到 `CommentedMap.insert()` 的方法签名,这里是源代码的链接。https://github.com/commx/ruamel-yaml/blob/a1b222e22a20365b2a338b0281f4b8c2b133da7e/comments.py#L882。如果您想添加类型声明,可以通过“from ruamel.yaml.comments import CommentedMap”导入它。 (2认同)

nur*_*urp 7

您必须将您的字典初始化为 OrderedDict。创建一个新的空 OrderedDict,遍历原始字典的所有键,并在键名称匹配时在之前/之后插入。

from pprint import pprint
from collections import OrderedDict


def insert_key_value(a_dict, key, pos_key, value):
    new_dict = OrderedDict()
    for k, v in a_dict.items():
        if k==pos_key:
            new_dict[key] = value  # insert new key
        new_dict[k] = v
    return new_dict


mydict = OrderedDict([('Name', 'Zara'), ('Age', 7), ('Class', 'First')])
my_new_dict = insert_key_value(mydict, "Phone", "Age", "1234")
pprint(my_new_dict)
Run Code Online (Sandbox Code Playgroud)

  • 不适用于 CPython 3.6 或任何其他 Python 3.7。`dict` 现在保持插入顺序,无需为此使用 `OrderedDict` (3认同)

cs9*_*s95 5

在python <3.7(或cpython <3.6)上,您无法控制标准字典中对的排序。

如果您打算经常执行任意插入,我的建议是使用列表存储键,并使用字典存储值。

mykeys = ['Name', 'Age', 'Class']
mydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'} # order doesn't matter

k, v = 'Phone', '123-456-7890'

mykeys.insert(mykeys.index('Name')+1, k)
mydict[k] = v

for k in mykeys:
    print(f'{k} => {mydict[k]}')

# Name => Zara
# Phone => 123-456-7890
# Age => 7
# Class => First
Run Code Online (Sandbox Code Playgroud)

如果您打算用其内容不太可能改变的顺序来初始化字典,则可以使用collections.OrderedDict保持插入顺序的结构。

from collections import OrderedDict

data = [('Name', 'Zara'), ('Phone', '1234'), ('Age', 7), ('Class', 'First')] 
odict = OrderedDict(data)
odict
# OrderedDict([('Name', 'Zara'),
#              ('Phone', '1234'),
#              ('Age', 7),
#              ('Class', 'First')])
Run Code Online (Sandbox Code Playgroud)

请注意,OrderedDict它不支持在任意位置插入(它只记住将键插入字典中的顺序)。

  • @DeepApp。解决方案很简单。将字典转换为列表。示例:`dictAsList = [(k, v) for k, v in yourDict.items()]`。现在您只需要迭代“dictAsList”并将项目插入您喜欢的位置。 (2认同)
  • 如果您从 YAML 开始,那么您不一定会保留 *YAML 文档中提供的密钥顺序*。如果您想保留顺序,最好使用“RoundTripLoader”,它是为此目的而制作的(除其他外)。 (2认同)