Loop Through All Nested Dictionary Values

Loop through all nested dictionary values?

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))

How to iterate through a nested dict?

As the requested output, the code goes like this

    d = {'dict1': {'foo': 1, 'bar': 2}, 'dict2': {'baz': 3, 'quux': 4}}

for k1,v1 in d.iteritems(): # the basic way
temp = ""
temp+=k1
for k2,v2 in v1.iteritems():
temp = temp+" "+str(k2)+" "+str(v2)
print temp

In place of iteritems() you can use items() as well, but iteritems() is much more efficient and returns an iterator.

Hope this helps :)

Loop through nested dictionary, replacing values with items from a list

Your dictionary comprehension is creating dictionary elements for every item in the list each time. But since you give them all the same key topic, only the last one is in the resulting dictionary. That's why you keep getting "topic": 6.

Use zip() to iterate through the dictionary keys and list elements in parallel, rather than nesting them. And there's no need to use update() if you're just setting one key of the dictionary, just assign to that key.

def update_dic(dictionary):
for k, v in zip(dictionary, topics):
dictionary[k]['topic'] = v

Iterate through nested dictionary values and return an ordered list based on dict's values

Try:

all_keys = set(k for v in transportation_cost.values() for k in v.keys())
out = {
k: [
*sorted(
transportation_cost.keys(), key=lambda x: transportation_cost[x][k]
)
]
for k in all_keys
}
print(out)

Prints:

{
"Huawei": ["Fac-2", "Fac-3", "Fac-5", "Fac-1", "Fac-4"],
"Motorolla": ["Fac-5", "Fac-3", "Fac-4", "Fac-2", "Fac-1"],
"Apple": ["Fac-4", "Fac-1", "Fac-5", "Fac-2", "Fac-3"],
"Nokia": ["Fac-3", "Fac-5", "Fac-4", "Fac-2", "Fac-1"],
"Samsung": ["Fac-2", "Fac-4", "Fac-1", "Fac-3", "Fac-5"],
}

How to loop through all nested dictionary to give all the parent key concatenated and its value

The answer of script0 results in an output that starts with a forward slash (/). I modified script0's code a little:

def flatten(x, parent=''):
for key in x.keys():
if isinstance(x[key], dict) and parent == '': flatten(x[key], key)
elif isinstance(x[key], dict) and parent != '': flatten(x[key], f"{parent}/{key}")
elif not isinstance(x[key], dict) and parent == '': print(f"{key}: {x[key]}")
else: print(f"{parent}/{key}: {x[key]}")

dictionary= {'items': { 'heading': 'Maps','description':'Maps123','imagepath':'/music/images/','config':{'config1':12,'config2':123}},'db':{'username':'xyz','password':'xyz'},'version':'v1'}

flatten(dictionary)

Output (without the leading /):

items/heading: Maps
items/description: Maps123
items/imagepath: /music/images/
items/config/config1: 12
items/config/config2: 123
db/username: xyz
db/password: xyz
version: v1

Please note that you could also create a new dictionary with the left-hand side of the output as the keys and the right-hand side as the values.

For example:

new_dict = {}

def flatten(x, parent=''):
for key in x.keys():
if isinstance(x[key], dict) and parent == '': flatten(x[key], key)
elif isinstance(x[key], dict) and parent != '': flatten(x[key], f"{parent}/{key}")
elif not isinstance(x[key], dict) and parent == '': new_dict[key] = x[key]
else: new_dict[f"{parent}/{key}"] = x[key]

dictionary= {'items': { 'heading': 'Maps','description':'Maps123','imagepath':'/music/images/','config':{'config1':12,'config2':123}},'db':{'username':'xyz','password':'xyz'},'version':'v1'}

flatten(dictionary)
print(new_dict)

Output:

{'items/heading': 'Maps', 'items/description': 'Maps123', 'items/imagepath': '/music/images/', 'items/config/config1': 12, 'items/config/config2': 123, 'db/username': 'xyz', 'db/password': 'xyz', 'version': 'v1'}

How to iterate through an N-level nested dictionary in Python?

try out this code

it also supports a combination of levels

from typing import List, Tuple

def iterate_multilevel_dictionary(d: dict):
dicts_to_iterate: List[Tuple[dict, list]] = [(d, [])]
'''
the first item is the dict object and the second object is the prefix keys
'''
while dicts_to_iterate:
current_dict, suffix = dicts_to_iterate.pop()
for k, v in current_dict.items():
if isinstance(v, dict):
dicts_to_iterate.append((v, suffix + [k]))
else:
yield suffix + [k] + [v]

if __name__ == '__main__':
d_level1 = {"a": 1, "b": 2, "c": 3}
print(f"test for {d_level1}")
for items in iterate_multilevel_dictionary(d_level1):
print(items)
d_level2 = {"group_1": {"a": 1}, "group_2": {"b": 2, "c": 3}}
print(f"test for {d_level2}")
for items in iterate_multilevel_dictionary(d_level2):
print(items)

d_level3 = {"collection_1": d_level2}
print(f"test for {d_level3}")
for items in iterate_multilevel_dictionary(d_level3):
print(items)

d_level123 = {}
[d_level123.update(i) for i in [d_level1, d_level2, d_level3]]
print(f"test for {d_level123}")
for items in iterate_multilevel_dictionary(d_level123):
print(items)

the outputs is:

test for {'a': 1, 'b': 2, 'c': 3}
['a', 1]
['b', 2]
['c', 3]
test for {'group_1': {'a': 1}, 'group_2': {'b': 2, 'c': 3}}
['group_2', 'b', 2]
['group_2', 'c', 3]
['group_1', 'a', 1]
test for {'collection_1': {'group_1': {'a': 1}, 'group_2': {'b': 2, 'c': 3}}}
['collection_1', 'group_2', 'b', 2]
['collection_1', 'group_2', 'c', 3]
['collection_1', 'group_1', 'a', 1]
test for {'a': 1, 'b': 2, 'c': 3, 'group_1': {'a': 1}, 'group_2': {'b': 2, 'c': 3}, 'collection_1': {'group_1': {'a': 1}, 'group_2': {'b': 2, 'c': 3}}}
['a', 1]
['b', 2]
['c', 3]
['collection_1', 'group_2', 'b', 2]
['collection_1', 'group_2', 'c', 3]
['collection_1', 'group_1', 'a', 1]
['group_2', 'b', 2]
['group_2', 'c', 3]
['group_1', 'a', 1]

using recursion is another approach but I thought writing without recursion is more challenging and more efficient :)

How to iterate through a nested dictionary with varying depth, and make a copy with value representing the path?

The most efficient way to do this would be using the same recursive function to not generate excess performance overhead. To copy the dictionary you can use copy.deepcopy() and then take that copy through the function, but replace the values instead of just printing the path:

import copy

data = {'n11': {'n12a': {'n13a': 10, 'n13b': "some text"}, 'n12b': {'n13c': {'n14a': 40}}}, 'n21': {'n22a': 20}}

def myreplace(d, path=[]):
for k, v in d.items():
if isinstance(v, dict):
myreplace(v, path + [k])
else:
print('_'.join(path + [k]))
d[k] = '_'.join(path + [k])
return d

copy_of_data = copy.deepcopy(data)
copy_of_data = myreplace(copy_of_data)
print(data)
print(copy_of_data)

I had to modify the original function slightly to get it working.

Python how to iterate over nested dictionary and change values?

You could use a dict here to hold the price multipliers, and iterate through all orders with nested for loops.

exchanges = {
'exchange1': [{'price': 9656.04, 'side': 'bid', 'size': 0.16, 'timestamp': 1589504786},
{'price': 9653.97, 'side': 'ask', 'size': 0.021, 'timestamp': 1589504786}],
'exchange2': [{'price': 9755.3, 'side': 'bid', 'size': 27.0, 'timestamp': 1589504799},
{'price': 9728.0, 'side': 'bid', 'size': 1.0, 'timestamp': 1589504799}]
}

price_multipliers = {
'bid': 0.99,
'ask': 1.01
}

for orders in exchanges.values():
for order in orders:
order["price"] *= price_multipliers[order["side"]]

Iterating over nested dictionary returns only first element

The problem is that when you call return myPrint(v, k) for the first time you compute the values for the first dictionary and then return instead of continuing to the other values in the for loop.

Changing the function to:

def myPrint(d, key=""):
output = {}
for k, v in d.items():
i = 0
if isinstance(v, dict):
output.update(myPrint(v, k))
else:
for value in d.values():
newkey = (f"{i}_{key}")
output[newkey] = value
i += 1
return output

will return a big dictionary, for you example:

{'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71],
'0_OuterVal1': [21, 19, 76], '1_OuterVal1': [1, 1, 1],
'0_OuterVal2': [1, 1, 96], '1_OuterVal2': [10, 9, 7],
'0_OuterVal3': [0, 2, 6], '1_OuterVal3': [1, 911, 718],
'0_OuterVal4': [12, 13, 9], '1_OuterVal4': [1000, 910, 701],
'0_OuterVal5': [110, 211, 961], '1_OuterVal5': [10, 911, 918]}

However, the function can be nicely packed in a non-recursive way as follow:

output = [{f'{ii}_{k}': vv  for (k, v) in source.items() for ii, (kk, vv) in enumerate(v.items())}]


Related Topics



Leave a reply



Submit