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
Answer from 0x0 on Stack OverflowThe 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.
How to loop through a nested dictionary
How to iterate over nested dictionaries in a LIST, using for loop
How to loop over nested dictionaries of n length?
Ways to improve efficiency in looping through a nested dictionary
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.
Well I can suggest a semi-hacky solution where you use set_fact a couple times to construct a list of dicts that you can probably use?
- hosts: localhost
vars:
nova_flavors:
- disk: 10
name: m1.tiny
properties:
disk_read_bytes_sec: 12500000
disk_read_iops_sec: 1000
disk_write_bytes_sec: 3125000
ram: 1
- disk: 10
name: m1.small
properties:
vif_outbound_burst: 7500000
vif_outbound_peak: 25000
ram: 2
tasks:
- set_fact:
aslist: |
[
{% for item in nova_flavors %}
{% for prop in item.properties.keys() %}
{{ '{' }} 'name':'{{ item.name }}','propname':'{{ prop }}','propvalue':{{item.properties[prop]}} {{ '}' }},
{% endfor %}
{% endfor %}
]
- debug:
var: aslist
Results.
TASK [debug] *******************************************************************
ok: [localhost] => {
"aslist": [
{
"name": "m1.tiny",
"propname": "disk_write_bytes_sec",
"propvalue": 3125000
},
{
"name": "m1.tiny",
"propname": "disk_read_iops_sec",
"propvalue": 1000
},
{
"name": "m1.tiny",
"propname": "disk_read_bytes_sec",
"propvalue": 12500000
},
{
"name": "m1.small",
"propname": "vif_outbound_peak",
"propvalue": 25000
},
{
"name": "m1.small",
"propname": "vif_outbound_burst",
"propvalue": 7500000
}
]
}
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
I believe this would easily allow you to loop over the constructed lists setting the each property.
If I ignore the "I want to check the value first" part, I could solve this through templating instead, like this:
- name: set flavor properties:
command: >-
openstack flavor set
{%for prop in item.properties.items()%}--property
{{prop.0}}={{prop.1}} {%endfor %} {{ item.name }}
loop: "{{ nova_flavors }}"
That works, but it's ugly, and will result in everything being
changed every playbook run. I could munge the data before passing
it to ansible so that the properties keys is a list of lists instead
of a list of dicts, as in:
- disk: 10
name: m1.tiny
properties:
- [disk_read_bytes_sec, 12500000]
- [disk_read_iops_sec, 1000]
- [disk_write_bytes_sec, 3125000]
- [disk_write_iops_sec, 250]
- [vif_inbound_average, 2500]
- [vif_inbound_burst, 3750000]
- [vif_inbound_peak, 12500]
- [vif_outbound_average, 2500]
- [vif_outbound_burst, 3750000]
- [vif_outbound_peak, 12500]
ram: 1
vcpus: 1
- disk: 10
name: m1.small
properties:
- [disk_read_bytes_sec: 25000000]
- [disk_read_iops_sec: 2000]
- [disk_write_bytes_sec: 6250000]
- [disk_write_iops_sec: 500]
- [vif_inbound_average: 5000]
- [vif_inbound_burst: 7500000]
- [vif_inbound_peak: 25000]
- [vif_outbound_average: 5000]
- [vif_outbound_burst: 7500000]
- [vif_outbound_peak: 25000]
ram: 2
vcpus: 1
But that's somewhat less intuitive to read and write...and it's
effectively re-implementing the .items() method by hand.
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