简体   繁体   中英

Append to a nested list or dict in Python

I often find myself populating lists and dicts by reading in files line by line.

Let's say I'm reading in a list of people and their favourite foods:

ANNE      CHEESE  
ANNE      POTATO 
JOE       PEAS    
JOE       CHIPS   
JOE       FISH
BERNARD   LENTILS

To a Python dictionary:

{
 "ANNE"   : ["CHEESE", "POTATO"], 
 "JOE"    : ["PEAS",   "CHIPS",   "FISH"],
 "BERNARD": ["LENTILS"]
}

The general pattern I use is to read the file line by line, in each case checking if the key exists already before attempting to append. Today I decided to generalise this and write a safe_append function which would create the relevant object before appending to a list or setting a dictionary key:

def safe_append(list_object, list_key, list_value, value_dict_key= None):
    # Add empty dict if it does not already exist
    if list_key not in list_object:
        if value_dict_key is not None:
            list_object[list_key] = {}
        else: 
            list_object[list_key] = []
    # Append/set value
    if value_dict_key is not None:
        list_object[list_key][value_dict_key] = list_value
    else: 
        list_object[list_key].append(list_value)
    # Return object (for chaining)
    return list_object 

# Usage: dict in dict
x = {}
safe_append(x, "a","b",value_dict_key = "c")
>>> {"a":{"c":"b"}}
# Usage: list in dict
x = []
safe_append(x, "a","b")
>>> {"a":["b"]}

This seems rather clumsy and ugly. My question: Is there a better/more pythonic way to do this?

The better way is to use a defaultdict:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d["hello"].append(1)
>>> d["hello"].append(2)
>>> dict(d)
{'hello':[1, 2]}

If all your values are lists, then you can use the defaultdict. Otherwise you can get similar behaviour by chaining setdefault and append:

a = {}
for key,value in [("k1","v1"), ("k1","v2")]:
    a.setdefault(key,[]).append(value)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM