2

I have dicts of two types representing same data. These are consumed by two different channels hence their keys are different.

for example: Type A

{ 
  "key1": "value1",
  "key2": "value2",
  "nestedKey1" : {
      "key3" : "value3",
      "key4" : "value4"
   } 
}

Type B

{ 
  "equiKey1": "value1",
  "equiKey2": "value2",
  "equinestedKey1.key3" : "value3",
  "equinestedKey1.key4" : "value4"
}

I want to map data from Type B to type A. currently i am creating it as below

{
  "key1": typeBObj.get("equiKey1"),
   .....
}

Is there a better and faster way to do that in Python

holdenweb
  • 33,305
  • 7
  • 57
  • 77
Abhishek Jha
  • 935
  • 2
  • 10
  • 22
  • So you want to strip the leading `"equi"` from the keys and deposit them at the same relative positions in Type A? – holdenweb Dec 12 '18 at 10:42
  • 1
    key names are just for demonstration. These could be anything. I have used "equi" in short for equivalent key – Abhishek Jha Dec 12 '18 at 10:56
  • https://stackoverflow.com/questions/6027558/flatten-nested-python-dictionaries-compressing-keys – Masoud Dec 12 '18 at 11:05
  • I'd personally do it in a recursive function, and keep track of the nested path, and check `B` with that. May be some faster ways, but if you have like <10000 keys for example, the simple way won't really hurt speed. Also for the record, the `equi` bit only makes your question less clear. – Peter Dec 12 '18 at 11:09
  • I think the question needs to be less ambiguous before anyone can give a useful answer. Perhaps the complete output you require would clarify things? – holdenweb Dec 12 '18 at 11:17

1 Answers1

1

First, you need a dictionary mapping keys in B to keys (or rather lists of keys) in A. (If the keys follow the pattern from your question, or a similar pattern, this dict might also be generated.)

B_to_A = { 
  "equiKey1": ["key1"],
  "equiKey2": ["key2"],
  "equinestedKey1.key3" : ["nestedKey1", "key3"],
  "equinestedKey1.key4" : ["nestedKey1", "key4"]
}

Then you can define a function for translating those keys.

def map_B_to_A(d):
    res = {}
    for key, val in B.items():
        r = res
        *head, last = B_to_A[key]
        for k in head:
            r = res.setdefault(k, {})
        r[last] = val
    return res

print(map_B_to_A(B) == A) # True

Or a bit shorter, but probably less clear, using reduce:

def map_B_to_A(d):
    res = {}
    for key, val in B.items():
        *head, last = B_to_A[key]
        reduce(lambda d, k: d.setdefault(k, {}), head, res)[last] = val
    return res
tobias_k
  • 81,265
  • 12
  • 120
  • 179