Подтвердить что ты не робот

В Python у меня есть словарь. Как изменить ключи этого словаря?

Скажем, у меня довольно сложный словарь.

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

В любом случае, моя цель - сканировать каждый ключ в этом сложном многоуровневом словаре. Затем добавьте "abc" в конец каждой клавиши.

Итак, это будет:

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

Как вы это сделаете?

4b9b3361

Ответ 1

Ключи не могут быть изменены. Вам нужно будет добавить новый ключ с измененным значением, затем удалить старый или создать новый dict с пониманием dict или т.п.

Ответ 2

Например, например:

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" к каждой клавише словаря и любому значению, которое является словарем.

EDIT: Там также действительно классная версия 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}}))

Ответ 3

>>> 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}}

Ответ 4

Я понимаю, что вы не можете изменить ключи и вам нужно будет создать новый набор ключей и присвоить их значения тем, на которые указывали оригинальные клавиши.

Я бы сделал что-то вроде:

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)

Ответ 5

Я использую следующую служебную функцию, которую я написал, которая принимает целевой dict и другой dict, содержащий перевод, и переключает все ключи в соответствии с ним:

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}

Ответ 6

#! /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

Ответ 7

Что-то вроде этого

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') )

Мне нравится функциональный стиль, вы можете прочитать только последнюю строку и посмотреть, что она делает; -)

Ответ 8

здесь плотная небольшая функция:

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)

Ответ 9

Вы можете сделать это с помощью рекурсии:

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}}

Ответ 10

вы также должны учитывать, что существует возможность вложенных dicts во вложенных списках, которые не будут покрыты вышеупомянутыми решениями. Эта функция объявляет префикс и/или постфикс для каждой клавиши в dict.

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

Ответ 11

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

Ответ 12

Я использую это для преобразования docopt POSIX-совместимых ключей командной строки в ключи PEP8

(например, "--option" → "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

Ответ 13

Привет, Я новый пользователь, но нахожу ответ на тот же вопрос, я не могу получить что-то полностью функциональное для моей проблемы, я делаю этот маленький кусок пирога с полной вложенной заменой ключей, вы можете отправить список с помощью dict или dict. Наконец, ваши dicts могут иметь список с dict или more dict вложенным, и все это заменяется вашими новыми потребностями. Чтобы указать, какой ключ нужно заменить новым ключом, используйте параметр "to", отправляющий dict. В конце мой маленький пример. 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))

Ответ 14

Функциональное (и гибкое) решение: это позволяет применять произвольное преобразование к ключам (рекурсивно для встроенных диктов):

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

Давай попробуем; сначала мы определяем нашу функцию преобразования ключей, а затем применяем ее к примеру:

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

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

(примечание: если вы все еще используете Python 2.x, вам нужно заменить d.items() в последней строке на d.iteritems() - спасибо @Rudy за напоминание о необходимости обновить этот пост для Python 3).