I have a list of items:
my_list = ['first', 'second', 'third']
I need to convert this items into a dictionary (so I can access each element by it's name), and associate multiple counters to each element: counter1, counter2, counter3.
So I do the following:
counter_dict = {'counter1': 0, 'counter2': 0, 'counter3': 0}
my_dict = dict(zip(mylist, [counter_dict]*len(mylist)))
This way I obtain a nested dictionary
{
'first': {
'counter1': 0,
'counter2': 0,
'counter3': 0
},
'second': {
'counter1': 0,
'counter2': 0,
'counter3': 0
},
'third': {
'counter1': 0,
'counter2': 0,
'counter3': 0
}
}
The problem here is that each counter dictionary is not independent, so when I update one counter, all of them are updated.
The following line not only updates the counter2
of second
but also updates counter2
of first
and third
my_dict['second']['counter2'] += 1
{
'first': {
'counter1': 0,
'counter2': 1,
'counter3': 0
},
'second': {
'counter1': 0,
'counter2': 1,
'counter3': 0
},
'third': {
'counter1': 0,
'counter2': 1,
'counter3': 0
}
}
I am aware that by doing [counter_dict]*len(mylist)
I am pointing all dictionaries to a single one.
Question is, how can I achieve what I need creating independent dictionaries? At the end I need to:
Thanks a lot
You can use copy.deepcopy
to copy a dict and copy its contents.
import copy
Instead of [counter_dict]*len(mylist)
use:
[copy.deepcopy(counter_dict) for _ in mylist]
Try this one:
my_dict = {k: counter_dict.copy() for k in my_list}
Instead of zipping values - it's enough to iterate over keys and copy your counters to values using dict compression.
But note, that this will work only with one level counter_dict. If needed nested dictionary - use deepcopy
from copy
package:
from copy import deepcopy
my_dict = {k: deepcopy(counter_dict) for k in my_list}
Another aproach - using defaultdict
from collections
, so you dont even need to create dictionary with predefined counters:
from collections import defaultdict
my_dict = {k: defaultdict(int) for k in my_list}
使用列表推导而不是*
运算符,并为列表的每个元素创建一个新字典。
my_dict = dict(zip(mylist, [dict(counter_dict) for _ in mylist])
You can go and make a function that will create a counter_dict
whenever you want to assign one:
def create_counter_dict(length):
return {'counter{}'.format(n+1) : 0 for n in range(length)}
Then when you want to assign a counter_dict
to your my_dict
:
my_dict = dict(zip(my_list, [create_counter_dict(3) for _ in range(len(my_list))]))
This way you don't have to make a copy of your dictionary, and you can alter this factory function to your needs.
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.