В Python у меня есть словарь. Как мне изменить ключи этого словаря? - PullRequest
19 голосов
/ 06 февраля 2010

Допустим, у меня довольно сложный словарь.

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

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

Так что будет:

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

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

Ответы [ 14 ]

35 голосов
/ 06 февраля 2010

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

14 голосов
/ 06 февраля 2010

Например, вот так:

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}}))
9 голосов
/ 06 февраля 2010
>>> 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}}
6 голосов
/ 07 февраля 2010

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

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

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 голосов
/ 27 ноября 2011

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

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}
2 голосов
/ 06 февраля 2010
#! /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
1 голос
/ 16 июня 2014

Вот небольшая функция:

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)
1 голос
/ 06 февраля 2010

Нечто подобное

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

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

0 голосов
/ 17 февраля 2016

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

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}}
0 голосов
/ 11 марта 2015

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