从一对或多个名称映射到Python中的值

时间:2014-01-31 12:45:06

标签: python arrays dictionary

我有一个应用程序,其中有一组命名节点。对于每对节点,我想存储它们的连接值。节点会随着时间的推移而来,所以我无法初始化一个“数组”。名称不是顺序整数,而是任意对象ID或字符串名称。

我需要能够做到:

lookup(name1, name2) -> value

set(name1, name2, value)

并且,当新节点加入时,执行:

set(newname, [all other nodes], default_value)

假设对于每对,方向无关紧要。即,(name1,name2)应具有与(name2,name1)相同的值。

最明显的Python实现似乎是一个两级字典:

{ name1 : { name2: value, name3:value}, name2: {name1:value, name3:value}, ... etc. }

这是最好的方法吗?

更新

使用带有对的dict作为键的提议在Python内部可能更好。但是,我还得到了一个侧面约束,能够导出和导入数据集作为列表列表(为了支持Simics模拟器内的状态序列化) - 为此,两级映射是非常自然。但我想这对也会在那里工作。实际上很难说什么更好。

2 个答案:

答案 0 :(得分:2)

您可以使用frozenset()键:

{frozenset([name1, name2]): value, frozenset([name2, name3]): other_value}

优点是frozenset()个对象可以用作键,节点的顺序无关紧要; frozenset([name1, name2])等于frozenset([name2, name1])

要获取所有节点的列表,您必须使用:

all_nodes = reduce(frozenset.union, yourdict.keys())

如果这是Python 2,请改用yourdict.iterkeys()。然后,您可以从中生成所有可能的组合,以使用以下方式设置默认值:

from itertools import permutations:

for name1, name2 in permutations(all_nodes, r=2):
    key = frozenset([name1, name2])
    if key not in yourdict:
        yourdict[key] = default_value

或者,如果将整个结构包装在一个类中(可能是一个好主意),您可以添加一个跟踪使用的节点的附加索引,在更新实例时使该索引保持最新。

答案 1 :(得分:1)

或者,您可以使用带有元组的字典作为键

{(name1, name2) : value, (name1, name3) : value, (name2, name1) : value, ...}

而不是

{name1 : {name2 : value, name3 : value}, name2 : {name1 : value, ...}, ... etc.}

然后操作将如下所示:

values = {(name1, name2) : value, (name1, name3) : value, (name2, name1) : value, ...}

def lookup(name1, name2):
    return values[name1, name2]

def set(name1, name2, value):
    values[name1, name2] = value
    values[name2, name1] = value  # for symmetry

P.S。不要浪费内存作为默认连接值,您可以修改查找,如下所示:

def lookup(name1, name2):
   return values.get((name1, name2), default_value)

但在这种情况下,对于不在集合中的节点,您将获得default_value