如果我们有(a1, b1)
和(a2, b2)
,很容易使用字典来存储对应关系:
dict[a1] = b1
dict[a2] = b2
我们可以毫无问题地得到(a1, b1)
和(a2, b2)
。
但是,如果我们有(a1, b1, c1)
和(a2, b2, c2)
,是否有可能得到类似的东西:
dict[a1] = (b1, c1)
dict[b1] = (a1, c1)
在哪里可以使用a1
或b1
来取回三元组(a1, b1, c2)
?那有意义吗?我不太确定该问题要使用哪种数据类型。上面的方法可以工作,但是会有重复的数据。
基本上,如果我有一个三元组,我可以使用哪种数据类型,以便可以使用第一个或第二个值来取回三元组?
答案 0 :(得分:10)
您可以编写自己的映射数据结构,以允许add
进行三元组或任意大小的组,并使用__getitem__
恢复该组。
class GroupMap:
def __init__(self):
self.data = {}
def add(self, group):
for item in group:
self.data[item] = group
def __getitem__(self, item):
return self.data[item]
group = (1, 2, 3)
group_map = GroupMap()
group_map.add(group)
print(group_map[1]) # (1, 2, 3)
请注意,此GroupMap
可以用于任何大小的组,而不仅仅是三组。
上面的下一步是根据发生碰撞时想要的行为来扩展类以避免碰撞。
您可能想知道是否有更好的方法来表示一组连接的对象。答案不是真的。
假设您有一个包含{em> n 个顶点的graph。然后,要连接图形,您必须至少具有 n-1 条边。在上面的数据结构中,我在dict
中使用了 n 条目,这意味着该解决方案几乎是最优的。
为什么可以使用 n-1 条目?因为您随后需要遍历所有图形才能恢复整个组。因此,再使用一条边可以进行 O(1)查找,这可能是您可能要权衡的。
答案 1 :(得分:2)
如果您想继承dict
(以获得与dict
相关的所有其他方法,例如.get
和whatnot)的替代方法,并且仅 获得其他元素(由于某些原因)。您可以制作一本属于您自己的新词典
class TupleDict(dict):
def __setitem__(self, key, value):
assert isinstance(key, tuple)
for i, e in enumerate(key):
dict.__setitem__(self, e, key[:i] + key[i+1:] + (value,))
dict.__setitem__(self, value, key)
,然后将任何元组键分配给单个值(不确定我喜欢这种语法,但是我们可以使其不同或使用独立方法)
d = TriDict()
d[(1,2)] = 4
,您将得到__getitem__
的结果,返回不存在的其余元组。
>>> print(d[1])
(2, 4)
>>> print(d[2])
(1, 4)
print(d[4])
>>> (1, 2)
答案 2 :(得分:1)
字典只能存储键值对。
您可以使用运算符重载来制作自己的三元组字典,这样当您用三元组的任何成员建立索引时,您会得到另外两个三元组,也许是这样的:
class trictionary:
def __init__(self):
self.data = []
def add(self, group):
self.data.append(group)
def __getitem__(self, key):
for group in data: #Find the set the key belongs to.
if key in group:
return tuple(group)
这避免了复制数据,并具有以性能为代价寻找的功能。也许有更好的方法可以做到这一点。
答案 3 :(得分:1)
基于OlivierMelançons的答案,我想出了这一点-万一值在元组中的位置很重要:
class GroupMap:
def __init__(self, data=None):
self.data = {}
if data:
self.add(data)
def add(self, data):
for idx, key in enumerate(data):
self.data.setdefault(idx, {})[key] = data
def __getitem__(self, key):
# lookup in first index
return self.getby(0, key)
def getby(self, idx, key):
return self.data[idx].get(key)
data = ('a', 'b', 'c')
g = GroupMap(data)
more_data = ('b', 'a', 'z')
g.add(more_data)
assert g['a'] == data
assert g.getby(0, 'a') == data
assert g.getby(0, 'b') == more_data
assert g.getby(0, 'c') is None
assert g.getby(1, 'a') == more_data
assert g.getby(1, 'b') == data
assert g.getby(2, 'c') == data
assert g.getby(2, 'z') == more_data
assert id(data) == id(g['a']) == id(g.getby(1, 'b'))
答案 4 :(得分:0)
您的问题中的示例与主要问题有所出入:
基本上,如果我有一个三元组,我可以使用哪种数据类型,以便可以使用第一个或第二个值来取回三元组?
一个字典。分配键值对element
,triplet
(请参见@OlivierMelançon的答案):
代码
d = {}
for x in triplet:
d[x] = triplet
演示
d["a"]
# ('a', 'b', 'c')
d["b"]
# ('a', 'b', 'c')
d["c"]
# ('a', 'b', 'c')
OP要求明确以下方面的首选行为:
d[a1] = (b1, c1)
与f((a1, b1, c1))
(a1, b1, c1)
与(b1, a1, c1)
(a1, b1, c1)
3次或2元组子集的组合解决了这些问题,就有可能提出更详尽的解决方案。