在Python中声明一个多维字典

66

我需要在Python中创建一个二维字典。例如:new_dic[1][2] = 5

当我创建new_dic = {}并尝试插入值时,我会遇到KeyError错误:

new_dic[1][2] = 5
KeyError: 1

如何做到这一点?


目前还没有被接受的答案,我认为作者期望得到一个好的解决方案,该方案保留了多维数组的某些属性,但在稀疏情况下也能很好地循环遍历行或列元素。使用嵌套字典,您可以轻松选择“行”作为内部字典,然后迭代内部字典。但这并不对称,如果您想选择“列”并迭代相应的单元格,则代码看起来完全不同。 - Laurent Lyaudet
我认为使用一个支持多维get()方法的数据结构会非常不错。在一个“五维字典”上执行get([1, 1, None, None, 2])操作将返回一个“切片”——一个二维字典,其中第一和第二维的值为1,第五维的值为2,而第三和第四维的值是任意的。在大多数情况下,get()应该返回一个迭代器或者一个重复的子多维字典。如果是零维“切片”,则应该返回一个单元格。 - Laurent Lyaudet
8个回答

92

多维字典就是以字典为值的字典,形成了嵌套结构:

new_dic = {}
new_dic[1] = {}
new_dic[1][2] = 5

为了避免在new_dic [1]下的其他键中意外清除该嵌套对象,您需要每次检测是否已经创建了new_dic [1]

您可以使用各种技术简化创建嵌套字典;例如使用dict.setdefault()

new_dic.setdefault(1, {})[2] = 5

dict.setdefault() 只有在键值不存在时才将一个键值对设置为默认值,使您免于每次测试此操作的麻烦。

更简单的方法是使用collections.defaultdict() 类型自动创建嵌套字典:

from collections import defaultdict

new_dic = defaultdict(dict)
new_dic[1][2] = 5

defaultdict 只是标准 dict 类型的一个子类;每当您尝试访问映射中还不存在的键时,就会调用工厂函数来创建新值。这里使用的是dict() 可调用对象,在调用时生成一个空字典。

演示:

>>> 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}})

36

看一下这个:

def nested_dict(n, type):
    if n == 1:
        return defaultdict(type)
    else:
        return defaultdict(lambda: nested_dict(n-1, type))

然后:

new_dict = nested_dict(2, float)

现在您可以:

new_dict['key1']['key2'] += 5
您可以创建任意数量的维度,选择您想要的目标类型:
new_dict = nested_dict(3, list)
new_dict['a']['b']['c'].append(5)

结果将是:

new_dict['a']['b']['c'] = [5]

1
尝试使用这个(顺便说一下,这很棒)。但需要删除第二层项,比如“del new_dict['key1']['key2]”,但我得到的是一个对象不可订阅。 - Paul Chambers
1
我认为这个应该是被接受的答案。 - Tripp Kinetics

12

一种简单的方法是将元组作为常规字典的键。因此,您的示例变为:

new_dic[(1, 2)] = 5

缺点是所有用法都必须遵循这种略显笨拙的约定,但如果可以接受,那么这就是您所需要的。


这正是我所需要的完美方案:new_dic[("orange", "apple", "coconut")] = {"": ""} - ktang
2
好的答案。请注意,您不需要使用括号,new_dic[1,2] = 5 同样可以使用元组(1,2)作为键。 - markusk

11

简单来说,你可以使用defaultdict

from collections import defaultdict
new_dic = defaultdict(dict)
new_dic[1][2]=5
>>>new_dic
defaultdict(<type 'dict'>, {1: {2: 5}})

6

您可以尝试这个,如果它是字符串,那么它甚至更容易。

new_dic = {}
a = 1
new_dic[a] = {}
b = 2
new_dic[a][b] = {}
c = 5
new_dic[a][b]={c}

类型
new_dic[a][b]
>>>'5'

针对字符串类型

new_dic = {}
a = "cat"
new_dic[a] = {}
b = "dog"
new_dic[a][b] = {}
c = 5
new_dic[a][b] = {c}

类型

new_dic["cat"]["dog"]
>>>'5'

Dsw在这里做得非常好。我一直在寻找这样的解决方案。我可以基于此构建一个类似于多维字典的结构,并将值放在第二位。 - Bitart

3
你是指dict还是list
如果你是指dict,你想要第二层是另一个dict还是一个list
要使用dict,需要事先声明键。
所以,如果你需要在dicts中嵌套dicts,需要像这样做:
new_dic = {}
try:
    new_dic[1][2] = 5
except KeyError:
    new_dic[1] = {2:5}

3

这里有一个包含另一个字典作为键1值的字典:

>>> new_dic = {}
>>> new_dic[1] = {2:5}
>>> new_dic
{1: {2: 5}}

您在处理中遇到的问题。
new_dic={}
new_dic[1][2]=5

问题在于new_dic[1]不存在,所以你无法向它添加字典(或其他任何东西)。


-2
在项目中,我需要拥有一个2D类实例字典,其中索引是浮点数(坐标)。我的做法是使用默认字典创建2D字典,并将我的类名作为类型传递。例如:
class myCoordinates:
    def __init__(self, args)
    self.x = args[0]
    self.y = args[1]

然后当我尝试创建字典时:

table = mult_dim_dict(2, myCoordinates, (30, 30))

函数'mult_dim_dict'的定义如下:

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))

注意:您不能传递多个参数,而是可以传递一个元组,其中包含所有参数。如果在创建时您的类不需要传递任何变量,则函数的第三个参数将为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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接