Reputation: 953
I need to make a two dimensional dictionary in python. e.g. new_dic[1][2] = 5
When I make new_dic = {}
, and try to insert values, I get a KeyError
:
new_dic[1][2] = 5
KeyError: 1
How to do this?
Upvotes: 69
Views: 158453
Reputation: 503
For project, I needed to have 2D dict of class instances, where indeces are float numbers (coordinates). What I did, was to create 2D dict using default dict, and pass my class name as a type. For ex.:
class myCoordinates:
def __init__(self, args)
self.x = args[0]
self.y = args[1]
and then when I tried to create dictionary:
table = mult_dim_dict(2, myCoordinates, (30, 30))
where function 'mult_dim_dict' defined as:
def mult_dim_dict(dim, dict_type, params):
if dim == 1:
if params is not None:
return defaultdict(lambda: dict_type(params))
else:
return defaultdict(dict_type)
else:
return defaultdict(lambda: mult_dim_dict(dim - 1, dict_type, params))
Note: you cannot pass multiple arguments, instead you can pass a tuple, containing all of your arguments. If your class, upon creation, does not need any variables to be passed, 3rd argument of function will be None
:
class myCoors:
def __init__(self, tuple=(0, 0)):
self.x, self.y = tuple
def printCoors(self):
print("x = %d, y = %d" %(self.x, self.y))
def mult_dim_dict(dim, dict_type, params):
if dim == 1:
if params is not None:
return defaultdict(lambda: dict_type(params))
else:
return defaultdict(dict_type)
else:
return defaultdict(lambda: mult_dim_dict(dim - 1, dict_type, params))
dict = mult_dim_dict(2, myCoors, None)
dict['3']['2'].x = 3
dict['3']['2'].y = 2
dict['3']['2'].printCoors() # x = 3, y = 2 will be printed
dict = mult_dim_dict(2, myCoors, (30, 20))
dict['3']['2'].printCoors() # x = 30, y = 20 will be printed
Upvotes: -2
Reputation: 932
One simple way is to just use tuples as keys to a regular dictionary. So your example becomes this:
new_dic[(1, 2)] = 5
The downside is that all usages have to be with this slightly awkward convention, but if that's OK, this is all you need.
Upvotes: 12
Reputation: 39428
Check it out:
def nested_dict(n, type):
if n == 1:
return defaultdict(type)
else:
return defaultdict(lambda: nested_dict(n-1, type))
And then:
new_dict = nested_dict(2, float)
Now you can:
new_dict['key1']['key2'] += 5
You can create as many dimensions as you want, having the target type of your choice:
new_dict = nested_dict(3, list)
new_dict['a']['b']['c'].append(5)
Result will be:
new_dict['a']['b']['c'] = [5]
Upvotes: 38
Reputation: 502
u can try this, it is even easier if it is string
new_dic = {}
a = 1
new_dic[a] = {}
b = 2
new_dic[a][b] = {}
c = 5
new_dic[a][b]={c}
type
new_dic[a][b]
>>>'5'
For string
new_dic = {}
a = "cat"
new_dic[a] = {}
b = "dog"
new_dic[a][b] = {}
c = 5
new_dic[a][b] = {c}
type
new_dic["cat"]["dog"]
>>>'5'
Upvotes: 6
Reputation: 20359
Simply, you can use defaultdict
from collections import defaultdict
new_dic = defaultdict(dict)
new_dic[1][2]=5
>>>new_dic
defaultdict(<type 'dict'>, {1: {2: 5}})
Upvotes: 11
Reputation: 1124060
A multi-dimensional dictionary is simply a dictionary where the values are themselves also dictionaries, creating a nested structure:
new_dic = {}
new_dic[1] = {}
new_dic[1][2] = 5
You'd have to detect that you already created new_dic[1]
each time, though, to not accidentally wipe that nested object for additional keys under new_dic[1]
.
You can simplify creating nested dictionaries using various techniques; using dict.setdefault()
for example:
new_dic.setdefault(1, {})[2] = 5
dict.setdefault()
will only set a key to a default value if the key is still missing, saving you from having to test this each time.
Simpler still is using the collections.defaultdict()
type to create nested dictionaries automatically:
from collections import defaultdict
new_dic = defaultdict(dict)
new_dic[1][2] = 5
defaultdict
is just a subclass of the standard dict
type here; every time you try and access a key that doesn't yet exist in the mapping, a factory function is called to create a new value. Here that's the dict()
callable, which produces an empty dictionary when called.
Demo:
>>> new_dic_plain = {}
>>> new_dic_plain[1] = {}
>>> new_dic_plain[1][2] = 5
>>> new_dic_plain
{1: {2: 5}}
>>> new_dic_setdefault = {}
>>> new_dic_setdefault.setdefault(1, {})[2] = 5
>>> new_dic_setdefault
{1: {2: 5}}
>>> from collections import defaultdict
>>> new_dic_defaultdict = defaultdict(dict)
>>> new_dic_defaultdict[1][2] = 5
>>> new_dic_defaultdict
defaultdict(<type 'dict'>, {1: {2: 5}})
Upvotes: 96
Reputation: 87134
Here is a dictionary that contains another dictionary as the value for key 1:
>>> new_dic = {}
>>> new_dic[1] = {2:5}
>>> new_dic
{1: {2: 5}}
The problem that you had with
new_dic={}
new_dic[1][2]=5
is that new_dic[1]
does not exist, so you can't add a dictionary (or anything for that matter) to it.
Upvotes: 3
Reputation: 4086
Do you mean dict
or list
?
And if you mean dict
do you want the second level to be another dict
? or a list
?
For a dict
to work you need to have declared the keys ahead of time.
So if it's dicts
in dicts
you need something like this:
new_dic = {}
try:
new_dic[1][2] = 5
except KeyError:
new_dic[1] = {2:5}
Upvotes: 3