我有两本词典:
source = {'a': 10, 'b': 20, 'c': 30}
destination = {'x': None, 'y': None, 'z': None, 'qq': 'Some value'}
我想根据一些预设映射将源字典映射到目标,例如:
a -> y
b -> z
c -> x
我可以创建一个函数来遍历目标字典并根据嵌套的 if 分配适当的值:
for k, v in destination.items():
if k == 'x':
destination[k] = source['c']
elif k == 'y':
destination[k] = source['a']
elif k == 'z':
destination[k] = source['b']
这似乎不太可扩展。
此外,我可能在源和目标中都有嵌套的键,这使循环更加复杂。
嵌套源/目标字典的示例可能是:
source_nest =
{
"a": {
"f": {
"k": 4,
"l": "cat"
}
},
"b": {
"s": "hit"
}
}
destination_nest =
{
"x": None,
"y": {
"q": None,
"r": 100
},
"z": None
}
使用示例映射,例如:
a/f/k -> y/q
a/f/l -> x
b/s -> z
进行这种重新映射的更有效方法是什么?
如果重要的话,这些字典是 JSON 文件的表示。
答案 0 :(得分:3)
将映射定义为另一个键和值反转的字典,然后使用带有三元 if/else 的字典推导来获得结果:
source = {'a': 10, 'b': 20, 'c': 30}
destination = {'x': None, 'y': None, 'z': None, 'qq': 'Some value'}
mapping = {"y": "a", "z": "b", "x": "c"} # note: key/values inversed
result = {k: source[mapping[k]] if k in mapping else v
for k, v in destination.items()}
# {'x': 30, 'y': 10, 'z': 20, 'qq': 'Some value'}
或者先将 source
映射到 destination
键,然后默认使用 get
:
mapping = {"a": "y", "b": "z", "c": "x"} # note: original order
source_mapped = {mapping.get(k, k): v for k, v in source.items()}
result = {k: source_mapped.get(k, v) for k, v in destination.items()}
对于嵌套的情况,您可能首先需要定义两个递归函数,让我们将它们称为 deep_set
和 deep_get
以使用多部分键在嵌套字典中设置和获取值。>
def deep_set(d, keys, val):
first, *rest = keys
if rest:
deep_set(d[first], rest, val)
else:
d[first] = val
def deep_get(d, keys):
first, *rest = keys
if rest:
return deep_get(d[first], rest)
else:
return d[first]
然后您可以再次定义映射,迭代对,并在目标目录中替换它们。这对字典理解不起作用,所以我将修改目标目录;如果您仍然需要,请务必先创建一个深拷贝。
mapping = [("a/f/k", "y/q"), ("a/f/l", "x"), ("b/s", "z")]
for s, t in mapping:
val = deep_get(source_nest, s.split("/"))
deep_set(destination_nest, t.split("/"), val)
# {'x': 'cat', 'y': {'q': 4, 'r': 100}, 'z': 'hit'}
答案 1 :(得分:0)
我使用映射的值作为源的键,并创建了一个名为 result 的键/值对字典
source = {'a': 10, 'b': 20, 'c': 30}
destination = {'x': None, 'y': None, 'z': None, 'qq': 'Some value'}
mapping = {"y": "a", "z": "b", "x": "c"}
result={k:source.get(v) for (k,v) in mapping.items()}
print(result)
输出:
{'y': 10, 'z': 20, 'x': 30}