очистка ключей dict во вложенном dict of dicts и списках dicts

#python #python-3.x #dictionary #nested

#python #python-3.x #словарь #вложенный

Вопрос:

У меня также есть вложенный dict со списком dicts, и некоторые из моих ключей имеют специальные символы. Каков наилучший способ удалить эти специальные символы из ключей.

Ниже, что я попытался, работает с dicts of dicts, но как я могу расширить его, чтобы также позаботиться о list of dicts.

 >>> a={"@pipeline": "start",  "@args": "-vv", "@start": "1598331637", "@info": {"@pipeline_stage": "tasks","@taskbegin": [{"@task": "1", "@time": "1598331638"}, {"@task": "2", "@time": "1598331638"}, {"@task": "3", "@time": "1598331638"}]}}
>>> a
{'@pipeline': 'start', '@args': '-vv', '@start': '1598331637', '@info': {'@pipeline_stage': 'tasks', '@taskbegin': [{'@task': '1', '@time': '1598331638'}, {'@task': '2', '@time': '1598331638'}, {'@task': '3', '@time': '1598331638'}]}}
>>> def _clean_keys(d):
...     return {''.join(filter(str.isalnum, k)): _clean_keys(v) for k, v in d.items()} if isinstance(d, dict) else d
... 
>>> _clean_keys(a)
{'pipeline': 'start', 'args': '-vv', 'start': '1598331637', 'info': {'pipelinestage': 'tasks', 'taskbegin': [{'@task': '1', '@time': '1598331638'}, {'@task': '2', '@time': '1598331638'}, {'@task': '3', '@time': '1598331638'}]}}
>>> 
  

Как вы можете видеть, список taskbegin не очищен.

Ответ №1:

Использование рекурсии

Пример:

 a={"@pipeline": "start",  "@args": "-vv", "@start": "1598331637", "@info": {"@pipeline_stage": "tasks","@taskbegin": [{"@task": "1", "@time": "1598331638"}, {"@task": "2", "@time": "1598331638"}, {"@task": "3", "@time": "1598331638"}]}}
def _clean_keys(d):
    res = {}
    if isinstance(d, dict):
        for k, v in d.items():   
            k = ''.join(filter(str.isalnum, k))      
            if isinstance(v, list):                   #Check if type of value is list
                res[k] = [_clean_keys(i) for i in v]  #use recursion
            else:
                res[k]= _clean_keys(v)
            
    else:
        res = d           
        
    return res

print(_clean_keys(a))
  

Вывод:

 {'args': '-vv',
 'info': {'pipelinestage': 'tasks',
          'taskbegin': [{'task': '1', 'time': '1598331638'},
                        {'task': '2', 'time': '1598331638'},
                        {'task': '3', 'time': '1598331638'}]},
 'pipeline': 'start',
 'start': '1598331637'}
  

Ответ №2:

Попробуйте это, работает нормально

Код

 def clean_dict(val):
    if type(val) == list:
        return clean_list(val)
    if type(val) == dict:
        return {clean(k) : clean_dict(v) for k, v in val.items()}
    return val

def clean_list(val):
    return [clean_dict(v) for v in val]

def clean(val):
   ''.join([c for c in val if c.isalnum()])
  

Вывод

 a={"@pipeline": "start",  "@args": "-vv", "@start": "1598331637", "@info": {"@pipeline_stage": "tasks","@taskbe
gin": [{"@task": "1", "@time": "1598331638"}, {"@task": "2", "@time": "1598331638"}, {"@task": "3", "@time": "1
598331638"}]}}

clean_dict(a)
Out[8]:
{'pipeline': 'start',
 'args': '-vv',
 'start': '1598331637',
 'info': {'pipelinestage': 'tasks',
  'taskbegin': [{'task': '1', 'time': '1598331638'},
   {'task': '2', 'time': '1598331638'},
   {'task': '3', 'time': '1598331638'}]}}