通过key-tuple的第一项对字典进行分组的有效方法

时间:2014-08-17 12:44:41

标签: python dictionary

我有一个字典,其中键是索引的元组,值是int。我用它来表示矩阵的稀疏表示。

In [347]: M
Out[347]:
{(1, 0, 0): 2,
 (1, 1, 2): 3,
 (1, 1, 3): 1,
 (1, 2, 4): 5,
 (2, 1, 3): 4,
 (2, 2, 2): 1}

现在我需要对不同的子矩阵进行一些计算,为此我需要减去每个矩阵。我可以用两种不同的方式做到这一点:

方法#1: 根据第一个关键项创建一个嵌套字典组M

In [190]: for k,v in M.iteritems():
    newM[k[0]][(k[1],k[2])]=v

结果:

1 {(1, 2): 3, (0, 0): 2, (2, 4): 5, (1, 3): 1}
2 {(1, 3): 4, (2, 2): 1}

现在我可以使用密钥轻松访问每个子矩阵。但是我正在处理大矩阵,而且内存不足。

方法#2: 只有在我想进行计算时才提取每个子矩阵:

for i in xrange(number_of_submatrices):
    sub_M = {(idx[1],idx[2])=val for idx,val in M.iteritems() if idx[0]==i }  
    apply_computation(sub_M)

这个方法很慢,因为我每次需要迭代M并检查子矩阵的索引

我还尝试使用itertools.groupbyoperator.itemgetter的组合,但没有成功使其发挥作用。

总体而言,是否有更好的解决方案?或两种方法中的任何一种更快的解决方案?

1 个答案:

答案 0 :(得分:1)

要使用itertools.groupby,您需要先对输入进行排序:

>>> M = {(1, 0, 0): 2,
...      (1, 1, 2): 3,
...      (1, 1, 3): 1,
...      (1, 2, 4): 5,
...      (2, 1, 3): 4,
...      (2, 2, 2): 1}
>>>
>>> import itertools
>>> newM = {
...     key: {k[1:]: M[k] for k in grp}
...     for key, grp in
...     itertools.groupby(sorted(M), key=lambda k: k[0])
... }  # nested dict comprehension
>>> newM
{1: {(1, 2): 3, (0, 0): 2, (2, 4): 5, (1, 3): 1},
 2: {(1, 3): 4, (2, 2): 1}}