有没有一种简单的方法可以将一本字典映射到另一本字典?

时间:2021-02-11 21:31:41

标签: python dictionary

我有两本词典:

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 文件的表示。

2 个答案:

答案 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_setdeep_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}