Reputation: 35
If I have something like this:
dic = {"hi": 5, "test": {"apple": 2, "orange": 3}, "sa": "ok"}
and I want my output to be like this:
[("hi", 5), ("apple", 2), ("orange": 3), ("sa", "ok")]
with each key and value beside each other. I ignored the "test" key in the final output because it's value is a dictionary.
Upvotes: 0
Views: 1885
Reputation: 739
I think the best approach to solve this kind of problem is through recursion, just in case you face something very weird. For example a dictionary in a dictionary in a dictionary (dictionaryception) /s.
def flattenDict(aDict):
result = []
for i in aDict: #we iterate through the dictionary
if isinstance(aDict[i], dict): #if the value of the key is a dictionary
result.extend(flattenDict(aDict[i])) #recursion
else:
result.append((i, aDict[i])) #else we append the value in the result list.
return result
Output:
[('hi', 5), ('apple', 2), ('orange', 3), ('sa', 'ok')]
Upvotes: 1
Reputation: 25
Here is a proposition of how you can handle that, assuming ("orange": 3) in the output is instead ("orange", 3) :
def work(di):
def f(di):
for i in di:
if isinstance(di[i],dict):
yield f(di[i])
else:
yield (i,di[i])
result = []
for item in f(di):
result+=[item] if isinstance(item,tuple) else list(item)
return result
dic = {"hi": 5, "test": {"apple": 2, "orange": 3}, "sa": "ok"}
print(work(dic))
#Output
[('hi', 5), ('apple', 2), ('orange', 3), ('sa', 'ok')]
Upvotes: 0
Reputation: 8047
If ("orange": 3)
in the expected result in the original question is a typo and your desired result is a list of tuples, the simplest answer may be:
dic = {"hi": 5, "test": {"apple": 2, "orange": 3}, "sa": "ok"}
l = []
for key in dic.keys():
if isinstance(dic[key], dict):
l.extend(dic[key].items())
continue
l.append((key, dic[key]))
print l
results:
[('orange', 3), ('apple', 2), ('sa', 'ok'), ('hi', 5)]
Upvotes: 0
Reputation: 57033
A recursive solution:
from itertools import chain
def flatten(d):
return chain.from_iterable([(k,v)] if not isinstance(v,dict) else flatten(v)
for k,v in d.items())
list(flatten(dic))
#[('hi', 5), ('apple', 2), ('orange', 3), ('sa', 'ok')]
Upvotes: 1
Reputation: 966
A possible solution, which solves just two levels of nesting (As above) is the following.
def loop_dict(d: dict):
"""continue to pop until no more dict d"""
while d:
yield d.popitem()
output = []
for k, v in loop_dict(dic):
if type(v) == dict:
output.extend(loop_dict(v))
else:
output.append((k, v))
To go further you can implement some recursive calls. Which will basically go depth to find the deepest nest and propagate backwards.
Upvotes: 0