将嵌套字典中的所有键从camelCase转换为snake_case

ude*_*tha 6 python algorithm

我有一本类似这样的字典:

{
     'firstName': 'abc',
     'lastName': 'xyz',
     'favoriteMovies': ['Star Wars', 'The lone ranger'],
     'favoriteCountries': [
          {'country': 'China', 'capitalCity': 'Beiging'},
          {'country': 'India', 'capitalCity': 'New Delhi'}
     ]
}
Run Code Online (Sandbox Code Playgroud)

我想将其转换为snake_case,如下所示

{
    'first_name': 'abc',
    'last_name': 'xyz',
    'favorite_movies': ['Star Wars', 'The lone ranger'],
    'favorite_countries': [
        {'country': 'China', 'capital_city': 'Beiging'},
        {'country': 'India', 'capital_city': 'New Delhi'}
     ]
}  
Run Code Online (Sandbox Code Playgroud)

字典可以是任何长度深度。

我目前的解决方案是

import re

def convert_snake_case_to_camel_case(data):
    required_dict = {}

    for key, value in data.items():
        if type(value) == str:
            new_key = re.sub("([a-z0-9])([A-Z])", r"\1_\2", key).lower()
            required_dict[new_key] = value
        elif type(value) == list and all(list(map(lambda _: isinstance(_, str), value))):
            new_key = re.sub("([a-z0-9])([A-Z])", r"\1_\2", key).lower()
            required_dict[new_key] = value
        elif type(value) == list and all(list(map(lambda _: isinstance(_, dict), value))):
            new_key = re.sub("([a-z0-9])([A-Z])", r"\1_\2", key).lower()
            required_dict[new_key] = list(filter(convert_snake_case_to_camel_case, value))
    return required_dict
Run Code Online (Sandbox Code Playgroud)

但我没有得到嵌套数据的预期结果。

Aja*_*234 11

短递归版本:

import re
def to_snake(s):
  return re.sub('([A-Z]\w+$)', '_\\1', s).lower()

def t_dict(d):
   if isinstance(d, list):
      return [t_dict(i) if isinstance(i, (dict, list)) else i for i in d]
   return {to_snake(a):t_dict(b) if isinstance(b, (dict, list)) else b for a, b in d.items()}
Run Code Online (Sandbox Code Playgroud)
data = {'firstName': 'abc', 'lastName': 'xyz', 'favoriteMovies': ['Star Wars', 'The lone ranger'], 'favoriteCountries': [{'country': 'China', 'capitalCity': 'Beiging'}, {'country': 'India', 'capitalCity': 'New Delhi'}]} 
print(t_dict(data))
Run Code Online (Sandbox Code Playgroud)

输出:

{'first_name': 'abc', 'last_name': 'xyz', 
 'favorite_movies': ['Star Wars', 'The lone ranger'], 
 'favorite_countries': [
    {'country': 'China', 'capital_city': 'Beiging'}, 
    {'country': 'India', 'capital_city': 'New Delhi'}
  ]
}
Run Code Online (Sandbox Code Playgroud)


Mih*_*nut 5

你可以用regex这个。

def camel_to_snake(str):
   return re.sub(r'(?<!^)(?=[A-Z])', '_', str).lower()
Run Code Online (Sandbox Code Playgroud)

然后构建另一个递归函数,使用上述函数转换所有字典键。


Zar*_*chi 0

data = {
     'firstName': 'abc',
     'lastName': 'xyz',
     'favoriteMovies': ['Star Wars', 'The lone ranger'],
     'favoriteCountries': [
          {'country': 'China', 'capitalCity': 'Beiging'},
          {'country': 'India', 'capitalCity': 'New Delhi'}
     ]
}

new_data = {}
for key, value in data.items():
    new_key_list = ['_' + x.lower() if x.isupper() else x for x in key]
    new_key = ''.join(new_key_list)
    if isinstance(value[0],dict):
        new_value = []
        for item in value:
            temp_dict = {}
            for key2, value2 in item.items():
                new_key_list = ['_' + x.lower() if x.isupper() else x for x in key2]
                new_key = ''.join(new_key_list)
                temp_dict[new_key] = value2
            new_value.append(temp_dict)
        new_data[new_key] = new_value
    else:
        new_data[new_key] = value
Run Code Online (Sandbox Code Playgroud)

输出:

{'first_name': 'abc', 'last_name': 'xyz', 'favorite_movies': ['Star Wars', 'The lone ranger'], 'capital_city': [{'country': 'China', 'capital_city': 'Beiging'}, {'country': 'India', 'capital_city': 'New Delhi'}]}
Run Code Online (Sandbox Code Playgroud)