用映射字典的值替换嵌套字典中的占位符
Posted
技术标签:
【中文标题】用映射字典的值替换嵌套字典中的占位符【英文标题】:Replace placeholder in nested dict with values of mapping dict 【发布时间】:2017-01-13 02:10:54 【问题描述】:我有一个嵌套字典,它可以在键和值中包含占位符。
example_dict = 'dict1': '%(map3)s': 'data': 'tmp',
'%(map2)s': 'freshdata': 'testtest',
'dict2': '%(map3)s': 'data': '%(map1)s', '%(map3)s': 'status': 'available'
我有一个映射字典,带有占位符映射:
mapping_dict=
"map1": [1,2,2],
"map2": "qwerz",
"map3": "asdfasdf"
如果占位符位于 VALUE 位置,mapping_dict 的相应映射也可能包含另一个数据类型而不是字符串作为值,例如列表或整数。如何将此数据类型传递给原始字典?我不知道如何制作占位符,例如列表。
信息:mapping_dict 包含的键可能比给定的example_dict 包含的键多。
我想要一个函数,用 mapping_dict 的值替换给定字典的占位符。
什么是一个好的递归实现?
【问题讨论】:
这是一个简单的 (a) iterate-on-base-type, (b) inspect-item-type, (c) goto a;直到你得到一个字符串或不可迭代的类型......你有什么问题? 列表不能是字典键。除非您要使用列表的字符串表示形式。 【参考方案1】:使用堆栈来导航键值对,您可以弹出键来重命名它们,对于值,做同样的事情,除了尝试看看您是否可以使用ast.literal_eval
将它们评估为 Python 文字来处理您的列表情况.
import ast
from copy import deepcopy
example_dict =
'dict1':
'%(map3)s': 'data': 'tmp',
'%(map2)s': 'freshdata': 'testtest'
,
'dict2':
'%(map3)s': 'data': '%(map1)s'
mapping_dict=
"map1": [1,2,2],
"map2": "qwerz",
"map3": "asdfasdf"
def sub_placeholders(orig, subs):
d = deepcopy(orig)
todo = [d]
while todo:
nxt = todo.pop()
for k, v in nxt.items():
nxt[k % mapping_dict] = nxt.pop(k)
if isinstance(v, dict):
todo.append(v)
elif isinstance(v, str):
nxt[k] = v % subs
try:
nxt[k] = ast.literal_eval(nxt[k])
except ValueError:
pass
return d
运行sub_placeholders(example_dict, example_mapping)
会给你:
'dict1': 'asdfasdf': 'data': 'tmp', 'qwerz': 'freshdata': 'testtest',
'dict2': 'asdfasdf': 'data': [1, 2, 2]
【讨论】:
【参考方案2】:这是一个递归选项,删除现有键并添加新键,它们应用“格式”和“命名”占位符。注意:在这种情况下,我们正在修改输入字典:
from pprint import pprint
example_dict = 'dict1': '%(map1)s': 'data': 'tmp', '%(map2)s': 'freshdata': 'testtest',
'dict2': '%(map1)s': 'data': '%(map1)s', '%(map2)s': 'status': 'available'
mapping_dict=
"map1": "asdf",
"map2": "qwerz",
def apply_placeholder(d, placeholder):
for key, value in d.items():
del d[key]
if isinstance(value, dict):
d[key % placeholder] = value
apply_placeholder(value, placeholder)
else:
d[key % placeholder] = value % placeholder
apply_placeholder(example_dict, mapping_dict)
pprint(example_dict)
打印:
'dict1': 'asdf': 'data': 'tmp', 'qwerz': 'freshdata': 'testtest',
'dict2': 'asdf': 'data': 'asdf', 'qwerz': 'status': 'available'
我不是特别喜欢del
调用和在这里修改输入对象,很高兴看到更好的选择。
【讨论】:
你可以在这里使用dict.pop
吗?
@NinjaPuppy 我觉得我正在接受面试,只是提出了一个糟糕的解决方案,面试官正试图帮助我指出正确的方向:)
对不起 - 不是那个意思 :)
诺诺,这只是我个人的恐惧/恐惧症和偶尔的主题噩梦。
还有一个问题:如果mapping_dict 包含数字(int)或列表(带int)并且我还想在输入dict 中有正确的数据类型,我需要更改什么? 【参考方案3】:
我认为这可以递归地做你想要的。它会创建原始字典的副本,然后对其进行修改,以便可以重复使用原始字典。
from pprint import pprint
import copy
try:
stringtype = basestring
except NameError:
stringtype = str # Python 3
def subst(mapping, replacements):
def do_subst(mapping, replacements):
for k, v in list(mapping.items()):
newk, newv = k, v
changed = False
if isinstance(k, stringtype):
newk = k % replacements
if newk != k:
changed = True
if isinstance(v, stringtype):
newv = v % replacements
if newv != v:
changed = True
elif isinstance(v, dict):
newv = do_subst(v, replacements)
if newv != v:
changed = True
if changed:
del mapping[k]
mapping[newk] = newv
return mapping
return do_subst(copy.deepcopy(mapping), replacements)
example_dict = 'dict1': '%(map1)s': 'data': 'tmp',
'%(map2)s': 'freshdata': 'testtest',
'dict2': '%(map1)s': 'data': '%(map1)s',
'%(map2)s': 'status': 'available'
mapping_dict= "map1": "asdf", "map2": "qwerz"
print('Before')
pprint(example_dict)
result = subst(example_dict, mapping_dict)
print('After')
pprint(result)
输出:
Before
'dict1': '%(map1)s': 'data': 'tmp', '%(map2)s': 'freshdata': 'testtest',
'dict2': '%(map1)s': 'data': '%(map1)s',
'%(map2)s': 'status': 'available'
After
'dict1': 'asdf': 'data': 'tmp', 'qwerz': 'freshdata': 'testtest',
'dict2': 'asdf': 'data': 'asdf', 'qwerz': 'status': 'available'
【讨论】:
以上是关于用映射字典的值替换嵌套字典中的占位符的主要内容,如果未能解决你的问题,请参考以下文章
用点击的 span 标签的 innerHTML 替换占位符值