python - How to iterate through a nested dict? - Stack Overflow
python - Creating a nested dictionaries via for-loop - Stack Overflow
How to loop over nested dictionaries of n length?
python - Loop through all nested dictionary values? - Stack Overflow
Videos
Hiya, I'm developing a game as a hobby, and I am currently coding in a clothing shop. Every piece of clothing has a description, cost, and stat requirements. To organise this data, I've used nested dictionaries within a few class attributes.
Now I want the shopkeeper to have specific comment for some clothing brought, so I'd want to return/print the description every time a player buys a piece of clothing? How would I do that exactly?
My pseudo code/problem strategy has been to write a function, initiate a loop over the keys of the outer dictionary, then using a conditional to find the piece of clothing just brought, and looping through it's inner dictionary to find it's dictionary key, and printing out it's value, which is a string. Hope that helps you understand my thinking.
The following will work with multiple levels of nested-dictionary:
Copydef get_all_keys(d):
for key, value in d.items():
yield key
if isinstance(value, dict):
yield from get_all_keys(value)
d = {'dict1': {'foo': 1, 'bar': 2}, 'dict2': {'dict3': {'baz': 3, 'quux': 4}}}
for x in get_all_keys(d):
print(x)
This will give you:
Copydict1
foo
bar
dict2
dict3
baz
quux
keys() method returns a view object that displays a list of all the keys in the dictionary
Iterate nested dictionary:
Copyd = {'dict1': {'foo': 1, 'bar': 2}, 'dict2': {'baz': 3, 'quux': 4}}
for i in d.keys():
print i
for j in d[i].keys():
print j
OR
Copyfor i in d:
print i
for j in d[i]:
print j
output:
Copydict1
foo
bar
dict2
baz
quux
where i iterate main dictionary key and j iterate the nested dictionary key.
You can simply achieve the expected behavior using collections.defaultdict and a simple loop.
NB. I am emulating a file with a split text here
f = '''GPU;GeForce GTX 1070 Ti;430
CPU;AMD Ryzen 7 2700X;233
GPU;GeForce GTX 2060;400
CPU;Intel Core i7-11700;360
RAM;HyperX 16GB;180
PSU;Corsair RM850X;210'''
from collections import defaultdict
out = defaultdict(dict)
for line in f.split('\n'):
typ,name,price = line.split(';')
out[typ][name] = price
dict(out)
output:
>>> dict(out)
{'GPU': {'GeForce GTX 1070 Ti': '430', 'GeForce GTX 2060': '400'},
'CPU': {'AMD Ryzen 7 2700X': '233', 'Intel Core i7-11700': '360'},
'RAM': {'HyperX 16GB': '180'},
'PSU': {'Corsair RM850X': '210'}}
with a file:
with open('file.txt') as f:
for line in f:
# rest of the loop from above
It's this part. You're replacing the value of your dictionary key.
outer_dict[type] = inner_dict
Instead change it to add a new sub-key like this
type = parts[0]
name = parts[1]
price = int(parts[2])
outer_dict[type][name] = price # add `name` to the `type` dict as a new key
Hey there,
I have an dictionary (essentially json) and I'm trying to iterate over it. I cant share the dictionary but essentially i dont know how many times it will be nested. If it isn't nested there is data i need to return. Issue is depending on one of the values, it might have another dictionary i need to loop over. I'm having trouble conceptualizing how to even write this.
The stupid in me pictures it as a for loop for each nest (just assume ill never see a nesting of more than 10) and write the outputs i need to another list. I think the better way to handle this is recursion but I'm not super confident with it.
Is there any other way i can access all items of each nest without knowing how many nests?
Sorry if this is very arbitrary. I'm having difficulty myself even trying to explain it.
Cheers
As said by Niklas, you need recursion, i.e. you want to define a function to print your dict, and if the value is a dict, you want to call your print function using this new dict.
Something like :
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print("{0} : {1}".format(k, v))
There are potential problems if you write your own recursive implementation or the iterative equivalent with stack. See this example:
dic = {}
dic["key1"] = {}
dic["key1"]["key1.1"] = "value1"
dic["key2"] = {}
dic["key2"]["key2.1"] = "value2"
dic["key2"]["key2.2"] = dic["key1"]
dic["key2"]["key2.3"] = dic
In the normal sense, nested dictionary will be a n-nary tree like data structure. But the definition doesn't exclude the possibility of a cross edge or even a back edge (thus no longer a tree). For instance, here key2.2 holds to the dictionary from key1, key2.3 points to the entire dictionary(back edge/cycle). When there is a back edge(cycle), the stack/recursion will run infinitely.
root<-------back edge
/ \ |
_key1 __key2__ |
/ / \ \ |
|->key1.1 key2.1 key2.2 key2.3
| / | |
| value1 value2 |
| |
cross edge----------|
If you print this dictionary with this implementation from Scharron
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
You would see this error:
> RuntimeError: maximum recursion depth exceeded while calling a Python object
The same goes with the implementation from senderle.
Similarly, you get an infinite loop with this implementation from Fred Foo:
def myprint(d):
stack = list(d.items())
while stack:
k, v = stack.pop()
if isinstance(v, dict):
stack.extend(v.items())
else:
print("%s: %s" % (k, v))
However, Python actually detects cycles in nested dictionary:
print dic
{'key2': {'key2.1': 'value2', 'key2.3': {...},
'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}
"{...}" is where a cycle is detected.
As requested by Moondra this is a way to avoid cycles (DFS):
def myprint(d):
stack = list(d.items())
visited = set()
while stack:
k, v = stack.pop()
if isinstance(v, dict):
if k not in visited:
stack.extend(v.items())
else:
print("%s: %s" % (k, v))
visited.add(k)