Skip to content

Instantly share code, notes, and snippets.

@PatrikHlobil
Last active February 9, 2024 23:29
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save PatrikHlobil/9d045e43fe44df2d5fd8b570f9fd78cc to your computer and use it in GitHub Desktop.
Save PatrikHlobil/9d045e43fe44df2d5fd8b570f9fd78cc to your computer and use it in GitHub Desktop.
Get all keys or values of a nested dictionary or list in Python
def iterate_all(iterable, returned="key"):
"""Returns an iterator that returns all keys or values
of a (nested) iterable.
Arguments:
- iterable: <list> or <dictionary>
- returned: <string> "key" or "value"
Returns:
- <iterator>
"""
if isinstance(iterable, dict):
for key, value in iterable.items():
if returned == "key":
yield key
elif returned == "value":
if not (isinstance(value, dict) or isinstance(value, list)):
yield value
else:
raise ValueError("'returned' keyword only accepts 'key' or 'value'.")
for ret in iterate_all(value, returned=returned):
yield ret
elif isinstance(iterable, list):
for el in iterable:
for ret in iterate_all(el, returned=returned):
yield ret
@RabbitJackTrade
Copy link

RabbitJackTrade commented Sep 10, 2021

First, great job! Thanks.

Then, a follow up question (of course):
Is it possible to modify the function so it returns keys (for example) while maintaining their hierarchy/order?

For example:
emps = {'emp1': {'name': 'Abe', 'position': {'office':'Mgr'},'home':'tenant'}, 'emp2': {'name': 'Bom', 'position': {'office':'Mgr'},'home':'tenant'}}

for i in iterate_all(emps): print(i)

returns:
emp1 name position office home emp2 name position office home

Can it return instead
emp1
emp1/name
emp1/position
emp1/position/office
emp1/position/home
emp2
emp2/name
emp2/position
emp2/position/office
emp2/position/home

Sometime the position of an element in the tree is important; that's why I'm asking.

Thanks.

@mh-malekpour
Copy link

mh-malekpour commented Jun 1, 2022

def get_keys(dictionary):
    result = []
    for key, value in dictionary.items():
        if type(value) is dict:
            new_keys = get_keys(value)
            result.append(key)
            for innerkey in new_keys:
                result.append(f'{key}/{innerkey}')
        else:
            result.append(key)
    return result

@emblondel
Copy link

Very useful thanks!

@LiorBitton
Copy link

LiorBitton commented Jan 25, 2023

I used @mh-malekpour code and added support for objects that are nested inside of arrays.

def generic_items(dict_or_list):
	if type(dict_or_list) is dict:
		return dict_or_list.items()
	if type(dict_or_list) is list:
		return enumerate(dict_or_list)
def get_keys(dictionary):
	result = []
	for key, value in generic_items(dictionary):
		if type(value) is dict or type(value) is list:
			new_keys = get_keys(value)
			result.append(key)
			for innerkey in new_keys:
				result.append(f'{key}/{innerkey}')
		else:
			result.append(key)
	return result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment