Skip to content

Instantly share code, notes, and snippets.

@nitori
Created September 25, 2022 14:18
Show Gist options
  • Save nitori/7f097c07c47fae68def90531af2353dc to your computer and use it in GitHub Desktop.
Save nitori/7f097c07c47fae68def90531af2353dc to your computer and use it in GitHub Desktop.
Iterate over a nest dictionary/list with a specified path
def extract(obj, path: list[str]):
def _inner(_obj, _path: list[str], used_path: list):
if not _path:
yield tuple(used_path), _obj
return
current, *rest = _path
if current == '*':
# yield from all items on the current level
if isinstance(_obj, list):
for i, item in enumerate(_obj):
yield from _inner(item, rest, used_path + [i])
elif isinstance(_obj, dict):
for key, value in _obj.items():
yield from _inner(value, rest, used_path + [key])
else:
# yield from single item on the current level
if isinstance(_obj, dict):
yield from _inner(_obj[current], rest, used_path + [current])
elif isinstance(_obj, list):
yield from _inner(_obj[current], rest, used_path + [current])
return _inner(obj, path, [])
def main():
config = [
{
'123': {
'name': 'channel 1',
'users': {
'456': {
'name': 'user 1',
'roles': ['admin', 'moderator'],
},
'789': {
'name': 'user 2',
'roles': ['moderator'],
},
'101': {
'name': 'user 3',
'roles': [],
},
}
}
},
]
for (_, channel_id, _, user_id), user in extract(config, ['*', '*', 'users', '*']):
print(f'#{channel_id} @{user_id}')
print(f' {user["name"]}')
print(f' {user["roles"]}')
print()
# OUTPUT roughly:
"""
#123 @456
user 1
['admin', 'moderator']
#123 @789
user 2
['moderator']
#123 @101
user 3
[]
"""
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment