Reputation: 13329
Say I have this dictionary:
"pools": {
"JP": {
"longName": "Jackpot",
"poolTotal": 318400,
"shortName": "Jpot",
"sortOrder": 9
}
},
How would I output this so I have it like this:
pool_JP_longname: Jackpot
pool_JP_poolTotal: 318400
etc
etc
The Nesting should not be limited to 2 or 3 levels, so it should be generic.
Or another example:
{
"soccer": {
"X07": {
"date": "2013-11-22",
"poolType": "S10",
"code": "INT",
"closeTime": "20:00:00",
"poolStatus": "OP",
"pool": {
"1": {
"startRace": 1,
"matchs": {
"1": {
"teamA": "Ajax Cape Town",
"teamB": "Moroka Swallows",
"matchStatus": "OP"
},
"2": {
"teamA": "Bidvest Wits",
"teamB": "MP Black Aces",
"matchStatus": "OP"
}
}
}
}
}
}
}
Would look like this:
soccer_X07_data: "2013-11-22"
soccer_X07_poolType: "S10"
etc
soccer_X07_pool_1_matchs_1_teamA
soccer_X07_pool_1_matchs_1_teamB
etc
I had started doing it like this, but this is not correct:
def iterTool(json_data, key_string):
for root_key, item in sorted(json_data.items(), key=itemgetter(0)):
if type(json_data[root_key]) == dict:
key_string += "_%s" % root_key
if json_data[root_key].keys():
for parent_key in json_data[root_key]:
if type(json_data[root_key][parent_key]) in [unicode]:
print "%s_%s" % (key_string, parent_key)
# print key_string.split("_")
# pass
iterTool(json_data[root_key], key_string)
This would outout like this:
_soccer_X07_code
_soccer_X07_poolStatus
_soccer_X07_closeTime
_soccer_X07_poolType
_soccer_X07_date
_soccer_X07_pool_1_matchs_1_matchStatus
_soccer_X07_pool_1_matchs_1_teamA
_soccer_X07_pool_1_matchs_1_teamB
_soccer_X07_pool_1_matchs_1_10_matchStatus
_soccer_X07_pool_1_matchs_1_10_teamA
_soccer_X07_pool_1_matchs_1_10_teamB
_soccer_X07_pool_1_matchs_1_10_2_matchStatus
_soccer_X07_pool_1_matchs_1_10_2_teamA
_soccer_X07_pool_1_matchs_1_10_2_teamB
_soccer_X07_pool_1_matchs_1_10_2_3_matchStatus
_soccer_X07_pool_1_matchs_1_10_2_3_teamA
_soccer_X07_pool_1_matchs_1_10_2_3_teamB
_soccer_X07_pool_1_matchs_1_10_2_3_4_matchStatus
_soccer_X07_pool_1_matchs_1_10_2_3_4_teamA
_soccer_X07_pool_1_matchs_1_10_2_3_4_teamB
_soccer_X07_pool_1_matchs_1_10_2_3_4_5_matchStatus
_soccer_X07_pool_1_matchs_1_10_2_3_4_5_teamA
...
Now just another curveball..
Let say the dict looks like this:
{
"CAP": {
"countryName": "ZAF",
"displayName": "AN"
},
"SPA": {
"countryName": "AUs",
"displayName": "AG"
}
}
Then it wont make sense to flatten it but rather:
GENERIC_KEY:CAP, countryName:ZAF, displayName:AN
How would you detect this?
Upvotes: 0
Views: 95
Reputation: 122024
This will recursively flatten your dictionaries:
def flatten_dict(dct, output=None, prefix=None):
if output is None:
output = {}
if prefix is None:
prefix = []
for key in dct:
if isinstance(dct[key], dict):
flatten_dict(dct[key], output, prefix + [key])
else:
output["_".join(prefix + [key])] = dct[key]
return output
For your second example, I get:
{'soccer_X07_pool_1_matchs_2_teamA': 'Bidvest Wits',
'soccer_X07_pool_1_matchs_2_teamB': 'MP Black Aces',
'soccer_X07_pool_1_matchs_1_matchStatus': 'OP',
...}
Upvotes: 2
Reputation: 101052
A simple solution could look like this:
d = { ... }
def flatten(dic, stack=None):
if not stack: stack = []
for key,value in dic.iteritems():
new_stack = stack[:] + [key]
if isinstance(value, dict):
for result in flatten(value, new_stack):
yield result
else:
yield new_stack, value
# just print it:
for stack, value in flatten(d):
print '{}: {}'.format('_'.join(stack), value)
# create a new dict:
new_d = {'_'.join(stack): value for stack, value in flatten(d)}
Upvotes: 1
Reputation: 19030
This is a basic recursion problem (or one that can be solved with recursion):
Here is a contrived example that satisfies your first example (more or less):
d = {
"pools": {
"JP": {
"longName": "Jackpot",
"poolTotal": 318400,
"shortName": "Jpot",
"sortOrder": 9
}
}
}
def flattendict(d):
for k, v in d.items():
if isinstance(v, dict):
for x in flattendict(v):
yield "{}_{}".format(k, x)
else:
yield "{}_{}".format(k, v)
for item in flattendict(d):
print item
NB: I've left several issues for you to problem solve and investigate.
Upvotes: 0