复杂的字典引用,python

Complicated referencing with dictionaries, python

假设我有两个字典如下:

vertices_on_tetrahedron = {
    0: [0, 1, 3, 7],
    1: [0, 1, 5, 7],
    2: [0, 4, 5, 7],
    3: [0, 2, 3, 7],
    4: [0, 4, 6, 7],
    5: [0, 2, 6, 7],
}
data_on_tetrahedron = {
    0: [78, 79, 80],
    1: [111, 112, 113],
    2: [144, 145, 146],
    3: [45, 46, 47],
    4: [177, 178, 179],
    5: [201, 202, 203],
}

接下来,我要做的是制作这样的字典:

result = {
    0: [78, 79, 80, 111, 112, 113, 144, 145, 146, 45, 46, 47, 177, 178, 179, 201, 202, 203],
    1: [78, 79, 80, 111, 112, 113],
    2: [45, 46, 47, 201, 202, 203],
    3: [78, 79, 80, 45, 46, 47],
    4: [144, 145, 146, 177, 178, 179],
    5: [111, 112, 113, 144, 145, 146],
    6: [177, 178, 179, 201, 202, 203],
    7: [78, 79, 80, 111, 112, 113, 144, 145, 146, 45, 46, 47, 177, 178, 179, 201, 202, 203],
}

本词典可以通过以下方式获得(肯定还有其他方式)。首先,我需要将 dict vertices_on_tetrahedron 重新排列为一些临时的:

tets_sharing_vertex = {
    0: [0, 1, 2, 3, 4, 5],
    1: [0, 1],
    2: [3, 5],
    3: [0, 3],
    4: [2, 4],
    5: [1, 2],
    6: [4, 5],
    7: [0, 1, 2, 3, 4, 5]
}

这是一个字典,其中每个键代表字典vertices_on_tetrahedron的值列表中的一个数字,值是具有该数字的字典vertices_on_tetrahedron的键列表。

然后,最终结果是一个字典,其键等于字典tets_sharing_vertex的键,并且根据字典tets_sharing_vertex中的值列表从字典b中取出值。

我实现如下(我承认这很丑):

def find_tets_sharing_vertex(vertex,input_dict):
    tmp = []
    for k, v in input_dict.iteritems():
        if vertex in v:
            tmp.append(k)

    return tmp

result_lst = []
for vertex in vertices:
    tmp = find_tets_sharing_vertex(vertex, vertices_on_tetrahedron)
    result_lst.append([b[i] for i in tmp])

result_tmp = dict(zip(values,result_lst))
result = {}
for i in range(len(result_tmp)):
    result[i] = flatten(result_tmp[i])

这里,vertices 是字典 vertices_on_tetrahedron 的所有可能值条目的列表。函数 flatten() 展平列表列表:[[0], [1]] -> [0, 1].

从概念上讲,result_lst 解决了问题,但它看起来像这样:

[[[78, 79, 80], [111, 112, 113], [144, 145, 146], [45, 46, 47], [177, 178, 179], [201, 202, 203]], ... ]

这就是为什么我要用 result_tmpresult 多做一步。

此实现有效,但速度较慢,我实际上需要它来处理大型词典 vertices_on_tetrahedrondata_on_tetrahedronvertices_on_tetrahedron 的结构始终相同:每个键都有不超过 4 项的值列表。但是可能有成千上万的密钥。 vertices_on_tetrahedron 相同,每个值是一个不超过 3 项的列表。

不幸的是,我得到了这种形式的 vertices_on_tetrahedrondata_on_tetrahedron,所以我不能重新考虑更改数据结构来避免这种情况。

如果有人也可以推荐一些参考资料来阅读这类问题,我将不胜感激。

首先,从vertices_on_tetrahedron

构造tets_sharing_vertex
from pprint import pprint
from collections import defaultdict

tets_sharing_vertex = defaultdict(list)
for k, v in vertices_on_tetrahedron.items():
    for x in v:
        tets_sharing_vertex[x].append(k)

pprint(tets_sharing_vertex)

输出:

{0: [0, 1, 2, 3, 4, 5],
 1: [0, 1],
 2: [3, 5],
 3: [0, 3],
 4: [2, 4],
 5: [1, 2],
 6: [4, 5],
 7: [0, 1, 2, 3, 4, 5]}

其次,从data_on_tetrahedrontets_sharing_vertex

得到result
from itertools import chain

result = {k: list(chain.from_iterable(data_on_tetrahedron[x] for x in v)) for k, v in tets_sharing_vertex.items()}

pprint(result, width=100)

输出:

{0: [78, 79, 80, 111, 112, 113, 144, 145, 146, 45, 46, 47, 177, 178, 179, 201, 202, 203],
 1: [78, 79, 80, 111, 112, 113],
 2: [45, 46, 47, 201, 202, 203],
 3: [78, 79, 80, 45, 46, 47],
 4: [144, 145, 146, 177, 178, 179],
 5: [111, 112, 113, 144, 145, 146],
 6: [177, 178, 179, 201, 202, 203],
 7: [78, 79, 80, 111, 112, 113, 144, 145, 146, 45, 46, 47, 177, 178, 179, 201, 202, 203]}

我认为这会起作用:

result =dict((i, []) for i in range(8))
for l in vertices_on_tetrahedron.keys():
    for j in vertices_on_tetrahedron[l]:
            result[j].extend(data_on_tetrahedron[l])

以下应该比您当前的解决方案工作得更快:

import collections

result = collections.defaultdict(list)
[result[v2].extend(data_on_tetrahedron[k1]) for k1,v1 in vertices_on_tetrahedron.items() for v2 in v1]

print result

给予:

defaultdict(<type 'list'>, {0: [78, 79, 80, 111, 112, 113, 144, 145, 146, 45, 46, 47, 177, 178, 179, 201, 202, 203], 1: [78, 79, 80, 111, 112, 113], 2: [45, 46, 47, 201, 202, 203], 3: [78, 79, 80, 45, 46, 47], 4: [144, 145, 146, 177, 178, 179], 5: [111, 112, 113, 144, 145, 146], 6: [177, 178, 179, 201, 202, 203], 7: [78, 79, 80, 111, 112, 113, 144, 145, 146, 45, 46, 47, 177, 178, 179, 201, 202, 203]})

这是我的解决方案:

result = {}
for k,v in vorticies_on_tetrahedron:
    result[k] = [data_on_tetrahedron[i] for i in v]

如果你要多次使用它,你可以将它包装在一个函数中。