在Python中,我有一本字典。如何更改此词典的键?

时间:2010-02-06 14:04:55

标签: python dictionary

假设我有一本非常复杂的词典。

{'fruit':'orange','colors':{'dark':4,'light':5}}

无论如何,我的目标是在这个复杂的多级词典中扫描每个键。然后,将“abc”附加到每个键的末尾。

所以它将是:

{'fruitabc':'orange','colorsabc':{'darkabc':4,'lightabc':5}}

你会怎么做?

15 个答案:

答案 0 :(得分:35)

无法更改密钥。您将需要添加具有修改值的新键,然后删除旧键,或者创建具有词典理解等的新词典。

答案 1 :(得分:14)

例如:

def appendabc(somedict):
    return dict(map(lambda (key, value): (str(key)+"abc", value), somedict.items()))

def transform(multilevelDict):
    new = appendabc(multilevelDict)

    for key, value in new.items():
        if isinstance(value, dict):
            new[key] = transform(value)

    return new

print transform({1:2, "bam":4, 33:{3:4, 5:7}})

这会将“abc”附加到字典中的每个键以及任何字典值。

编辑:还有一个非常酷的Python 3版本,请查看:

def transform(multilevelDict):
    return {str(key)+"abc" : (transform(value) if isinstance(value, dict) else value) for key, value in multilevelDict.items()}

print(transform({1:2, "bam":4, 33:{3:4, 5:7}}))

答案 2 :(得分:9)

>>> mydict={'fruit':'orange','colors':{'dark':4,'light':5}}

>>> def f(mydict):
...  return dict((k+"abc",f(v) if hasattr(v,'keys') else v) for k,v in mydict.items())
... 
>>> f(mydict)
{'fruitabc': 'orange', 'colorsabc': {'darkabc': 4, 'lightabc': 5}}

答案 3 :(得分:6)

我的理解是你无法更改密钥,并且需要创建一组新密钥并将其值分配给原始密钥指向的密钥。

我会做类似的事情:

def change_keys(d):
  if type(d) is dict:
    return dict([(k+'abc', change_keys(v)) for k, v in d.items()])
  else:
    return d

new_dict = change_keys(old_dict)

答案 4 :(得分:5)

我使用以下实用程序函数,我编写了一个目标字典和另一个包含翻译的字典,并根据它切换所有键:

def rename_keys(d, keys):
    return dict([(keys.get(k), v) for k, v in d.items()])

所以初始数据:

data = { 'a' : 1, 'b' : 2, 'c' : 3 }
translation = { 'a' : 'aaa', 'b' : 'bbb', 'c' : 'ccc' }

我们得到以下信息:

>>> data
{'a': 1, 'c': 3, 'b': 2}
>>> rename_keys(data, translation)
{'aaa': 1, 'bbb': 2, 'ccc': 3}

答案 5 :(得分:2)

#! /usr/bin/env python

d = {'fruit':'orange', 'colors':{'dark':4,'light':5}}

def add_abc(d):
  newd = dict()
  for k,v in d.iteritems():
    if isinstance(v, dict):
      v = add_abc(v)
    newd[k + "abc"] = v
  return newd

d = add_abc(d)
print d

答案 6 :(得分:1)

像这样的东西

def applytoallkeys( dic, func ):
    def yielder():
        for k,v in dic.iteritems():
            if isinstance( v, dict):
                yield func(k), applytoallkeys( v, func )
            else:
                yield func(k), v
    return dict(yielder())

def appendword( s ):
    def appender( x ):
        return x+s
    return appender

d = {'fruit':'orange','colors':{'dark':4,'light':5}}
print applytoallkeys( d, appendword('asd') )

我有点像功能风格,你可以只阅读最后一行并看看它的作用; - )

答案 7 :(得分:1)

这是一个很小的功能:

def keys_swap(orig_key, new_key, d):
    d[new_key] = d.pop(orig_key)

针对您的特定问题:

def append_to_dict_keys(appendage, d):
    #note that you need to iterate through the fixed list of keys, because
    #otherwise we will be iterating through a never ending key list!
    for each in d.keys():
        if type(d[each]) is dict:
            append_to_dict_keys(appendage, d[each])
        keys_swap(each, str(each) + appendage, d)

append_to_dict_keys('abc', d)

答案 8 :(得分:0)

你可以用递归来做到这一点:

import collections
in_dict={'fruit':'orange','colors':{'dark':4,'light':5}}

def transform_dict(d):
    out_dict={}
    for k,v in d.iteritems():
        k=k+'abc'
        if isinstance(v,collections.MutableMapping):
            v=transform_dict(v)            
        out_dict[k]=v
    return out_dict
out_dict=transform_dict(in_dict)
print(out_dict)

# {'fruitabc': 'orange', 'colorsabc': {'darkabc': 4, 'lightabc': 5}}

答案 9 :(得分:0)

您还应该考虑嵌套列表中存在嵌套dicts的可能性,上述解决方案不会涵盖这些内容。此函数会为字典中的每个键添加前缀和/或后缀。

def transformDict(multilevelDict, prefix="", postfix=""):
"""adds a prefix and/or postfix to every key name in a dict"""
new_dict = multilevelDict
if prefix != "" or postfix != "":
    new_key = "%s#key#%s" % (prefix, postfix)
    new_dict = dict(map(lambda (key, value): (new_key.replace('#key#', str(key)), value), new_dict.items()))
    for key, value in new_dict.items():
        if isinstance(value, dict):
            new_dict[key] = transformDict(value, prefix, postfix)
        elif isinstance(value, list):
            for index, item in enumerate(value):
                if isinstance(item, dict):
                    new_dict[key][index] = transformDict(item, prefix, postfix)
return new_dict

答案 10 :(得分:0)

for k in theDict: theDict[k+'abc']=theDict.pop(k)

答案 11 :(得分:0)

我用它将docopt POSIX兼容的命令行密钥转换为PEP8密钥

(例如“--option” - >“选项”,“” - >“option2”,“FILENAME” - >“filename”)


arguments = docopt.docopt(__doc__)  # dictionary
for key in arguments.keys():
    if re.match('.*[-<>].*', key) or key != key.lower():
        value = arguments.pop(key)
        newkey = key.lower().translate(None, '-<>')
        arguments[newkey] = value

答案 12 :(得分:0)

嗨,我是新用户,但找到相同问题的答案,我无法完全解决我的问题,我用一个完整的嵌套替换键制作这个小蛋糕,你可以用dict或dict发送列表。 最后你的dicts可以有dict或更多dict嵌套的列表,它全部被你的新密钥需求所取代。 要指示哪个密钥要用新密钥替换,请使用&#34;到&#34;参数发送一个字典。 最后看看我的小例子。 P / D:对不起,我的英文不好。 =)

def re_map(value, to):
    """
    Transform dictionary keys to map retrieved on to parameters.
    to parameter should have as key a key name to replace an as value key name
    to new dictionary.
    this method is full recursive to process all levels of
    @param value: list with dictionary or dictionary
    @param to: dictionary with re-map keys
    @type to: dict
    @return: list or dict transformed
    """
    if not isinstance(value, dict):
        if not isinstance(value, list):
            raise ValueError(
                         "Only dict or list with dict inside accepted for value argument.")  # @IgnorePep8

    if not isinstance(to, dict):
        raise ValueError("Only dict accepted for to argument.")

    def _re_map(value, to):
        if isinstance(value, dict):
            # Re map dictionary key.
            # If key of original dictionary is not in "to" dictionary use same
            # key otherwise use re mapped key on new dictionary with already
            # value.
            return {
                    to.get(key) or key: _re_map(dict_value, to)
                    for key, dict_value in value.items()
            }
        elif isinstance(value, list):
            # if value is a list iterate it a call _re_map again to parse
            # values on it.
            return [_re_map(item, to) for item in value]
        else:
            # if not dict or list only return value.
            # it can be string, integer or others.
            return value

    result = _re_map(value, to)

    return result

if __name__ == "__main__":
    # Sample test of re_map method.
    # -----------------------------------------
    to = {"$id": "id"}
    x = []
    for i in range(100):
        x.append({
             "$id": "first-dict",
             "list_nested": [{
                 "$id": "list-dict-nested",
                 "list_dic_nested": [{
                    "$id": "list-dict-list-dict-nested"
                     }]
             }],
             "dict_nested": {
                 "$id": "non-nested"
             }
             })

    result = re_map(x, to)

    print(str(result))

答案 13 :(得分:0)

功能(和灵活)解决方案。这允许将任意变换应用于键(递归地用于嵌入的dicts):

def remap_dict(d, keymap_f):
  """returns a new dict by recursively remapping all of d's keys using keymap_f"""
  return dict([(keymap_f(k), remap_dict(v, keymap_f) if isinstance(v, dict) else v) 
    for k,v in d.iteritems()])

让我们尝试一下;首先我们定义我们的关键转换函数,然后将其应用于示例:

def transform_key(key):
  """whatever transformation you'd like to apply to keys"""
  return key + "abc"

remap_dict({'fruit':'orange','colors':{'dark':4,'light':5}}, transform_key)
{'fruitabc': 'orange', 'colorsabc': {'darkabc': 4, 'lightabc': 5}}

答案 14 :(得分:0)

基于@AndiDog的python 3版本,类似于@ sxc731的版本,但带有是否递归应用的标志:

        <button onclick=showText('text1')>Show text 1</button>
        <button onclick=showText('text2')>Show text 2</button>
        <button onclick=showText('text3')>Show text 3</button>
        <p id="text1"></p>
        <p id="text2"></p>
        <p id="text3"></p>