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.