Python 递归地替换字典中的字符
如果给定一个任意嵌套的字典,如何将所有点Python 递归地替换字典中的字符,python,string,dictionary,recursion,Python,String,Dictionary,Recursion,如果给定一个任意嵌套的字典,如何将所有点更改为下划线(在dict的键中) 我试着写两个循环,但是我只能使用两级嵌套字典 这个 { "brown.muffins": 5, "green.pear": 4, "delicious.apples": { "green.apples": 2 { } 。。。应成为: { "brown_muffins": 5, "green_pear": 4, "delicious_apples":
更改为下划线(在dict的键中)
我试着写两个循环,但是我只能使用两级嵌套字典
这个
{
"brown.muffins": 5,
"green.pear": 4,
"delicious.apples": {
"green.apples": 2
{
}
。。。应成为:
{
"brown_muffins": 5,
"green_pear": 4,
"delicious_apples": {
"green_apples": 2
{
}
有一种优雅的方法吗?您可以编写一个递归函数,如下所示
from collections.abc import Mapping
def rec_key_replace(obj):
if isinstance(obj, Mapping):
return {key.replace('.', '_'): rec_key_replace(val) for key, val in obj.items()}
return obj
当你用你在问题中展示的字典调用它时,你会得到一个新的字典,其中键中的点被替换为
s
{'delicious_apples': {'green_apples': 2}, 'green_pear': 4, 'brown_muffins': 5}
解释
在这里,我们只需检查当前对象是否是dict的实例,如果是,则迭代字典,替换键并递归调用函数。如果它实际上不是字典,则按原样返回。假设
仅存在于键中,并且字典的所有内容都是原始文本,真正便宜的方法是使用str()
或repr()
,进行替换,然后ast.literal\u eval()
将其取回:
d ={
"brown.muffins": 5,
"green.pear": 4,
"delicious_apples": {
"green.apples": 2
} # correct brace
}
结果:
>>> import ast
>>> ast.literal_eval(repr(d).replace('.','_'))
{'delicious_apples': {'green_apples': 2}, 'green_pear': 4, 'brown_muffins': 5}
如果字典的键之外有
,我们可以更仔细地替换,使用正则表达式查找类似'ke.y':
的字符串,只替换那些位:
>>> import re
>>> ast.literal_eval(re.sub(r"'(.*?)':", lambda x: x.group(0).replace('.','_'), repr(d)))
{'delicious_apples': {'green_apples': 2}, 'green_pear': 4, 'brown_muffins': 5}
如果您的字典非常复杂,在值和类似字典的字符串中有
。
,等等,请使用真正的递归方法。正如我在开始时所说的,这是一种廉价的方法。定义循环字典键/值的方法,如果键有点,则替换,如果值是另一个dict,则输入递归(调用相同的方法,但现在使用此dict)您尝试了什么?不要用“有两个循环”来表示“任意嵌套”。递归的美妙之处,baby@PeterWood-这是任何递归的可能性。如果结构嵌套得不是很深,它可能会很好。@PeterWood stack overflow,baby:p这也会在值中替换,though@cricket_007我想他说的是水果和糖果的整数。@erip-仍然不是OP问的,假设你没有{'my.key':\uu my\u method}
:P@erip理想的,它也应该对未来的访客有用,而不仅仅是针对具体的案例。非常有创意。为什么不使用dict
而不是Mapping
。相反,您可以稍微放宽条件,允许任何具有少量方法的类,使其看起来像字典。你可能想看看定义。请原谅我在这里缺乏知识。。还有一件事,这只是一个建议,你不认为用tr来包装它是安全的吗?除非
块可以避免达到最大迭代次数(如果这很重要),并在达到最大迭代次数时引发一个异常,或者对其采取任何控制措施…?@IronFist这不是生产就绪代码:D我不希望任何人按原样使用它。如果愿意,可以增加递归限制:-)