Home > database >  Python Nested Dictionary append
Python Nested Dictionary append

Time:06-09

done this millions of times in other languages by python method for this is escaping me.

Basically reading some data from database. Includes data like ID, Fruits, Colors, Name

I need to create an object / dictionary key on Name. Name then holds lists / dictionaries of Fruits and Colors.

{"greenhouse1": {"fruits": {"apples", "oranges"}
                {"colors": {"red","orange"}}

I'm iterating through the db by row and the Name key will appear more than once. When it does fruits or colors may already be populated and need to append.

namedict = {}
db_rows = execute_query(cursor, args.store_proc)

for row in db_rows:
  db_name = row.id
  db_fruit = row.fruit
  db_color = row.color
  if db_name in namedict:
    namedict[db_name]["fruits"].append(db_fruit)
    namedict[db_name]["color"].append(db_color)
  else:
    namedict[db_name]["fruits"] = [db_fruit]
    namedict[db_name]["color"] = [db_color]

CodePudding user response:

collections.defaultdict is your friend: If you access a new key of a defaultdict, it is automatically initialised with the provided function (list or set in this case). Because you want a dictionary (e.g. "greenhouse1") of dictionaries ("fruits", "colors") with lists as values (separate fruits and colors), we need a nested defaultdict. The following should work:

from collections import defaultdict

db = defaultdict(lambda: defaultdict(list))  # alternative: set instead of list
db['greenhouse1']['fruits'].append('apples')  # use `add` for sets
db['greenhouse1']['fruits'].append('oranges')
db['greenhouse1']['colors'] = ["red", "orange"]

db['greenhouse2']['fruits'].append('banana')

print(db)
# defaultdict(<function __main__.<lambda>()>,
#             {'greenhouse1': defaultdict(list,
#                          {'fruits': ['apples', 'oranges'],
#                           'colors': ['red', 'orange']}),
#              'greenhouse2': defaultdict(list, {'fruits': ['banana']})})

A defaultdict works like a regular dict, so don't get confused with the strange looking output. E.g. to access the fruits of greenhouse1 you can simply write db['greenhouse1']['fruits'] and you get back a list (or set).

CodePudding user response:

First, you need quotes around fruits and color in the dictionary keys.

Second, you can't create a nested dictionary element until you create the dictionary.

You can simplify the code by using collections.defaultdict. Since you want nested dictionaries, you need nested defaultdicts.

from collections import defaultdict

namedict = defaultdict(lambda: defaultdict(set))

for row in db_rows:
    namedict[row.id]['fruits'].add(row.fruit)
    namedict[row.id]['colors'].add)row.color)
  • Related