我有一个将3tuple映射到3tuple的字典,其中key-tuples有一些共同的元素
dict= { (a,b,c):(1,2,3),
(a,b,d):tuple1,
(a,e,b):tuple,
.
(f,g,h):tuple3,
.
.
.
tuple:tuple
}
现在如何在字典ie (1:2:3) and tuple1
这是计算机生成的,非常大,因此需要花费精力来确定任何X.
那么,我能做到这一点的好方法吗?
编辑:(f,g,*),(f,*,g)与tuple3的部分匹配也会有所帮助,但不是必需的。
答案 0 :(得分:8)
让我们假设您为遗失的密钥传递None
,那么您可以使用all
和zip
:
>>> from itertools import permutations
>>> import random
#create a sample dict
>>> dic = {k:random.randint(1, 1000) for k in permutations('abcde', 3)}
def partial_match(key, d):
for k, v in d.iteritems():
if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)):
yield v
...
>>> list(partial_match(('a', 'b', None), dic))
[541, 470, 734]
>>> list(partial_match(('a', None, 'b'), dic))
[460, 966, 45]
#Answer check
>>> [dic[('a', 'b', x)] for x in 'cde']
[541, 734, 470]
>>> [dic[('a', x, 'b')] for x in 'cde']
[966, 460, 45]
答案 1 :(得分:4)
你可以将你的字典重建成一个三重嵌套的字典。
dict= { ("foo", 4 , "q"): 9,
("foo", 4 , "r"): 8,
("foo", 8 , "s"): 7,
("bar", 15, "t"): 6,
("bar", 16, "u"): 5,
("baz", 23, "v"): 4
}
d = {}
for (a,b,c), value in dict.iteritems():
if a not in d:
d[a] = {}
if b not in d[a]:
d[a][b] = {}
d[a][b][c] = value
此处,d
相当于:
d = {
"foo": {
4:{
"q": 9,
"r": 8
},
8:{
"s": 7
}
},
"bar":{
15:{
"t": 6
}
16:{
"u": 5
}
},
"baz":{
23{
"v": 4
}
}
}
现在,您可以轻松地遍历可能的第三个键,给定第一个和第二个键。
#find all keys whose first two elements are "foo" and 4
a = "foo"
b = 4
for c in d[a][b].iterkeys():
print c
结果:
q
r
这仅适用于匹配第三个键。例如,鉴于第三个和第一个键,您将无法找到所有第二个键。
答案 2 :(得分:1)
可能还有其他方法,但假设您只需要进行一次搜索(换句话说,可能有办法为重复搜索构建更好的数据结构): (请注意,这会在多个可能的位置使用'*'处理任意加长的元组)
def match(tup,target):
if len(tup) != len(target):
return False
for i in xrange(len(tup)):
if target[i] != "*" and tup[i] != target[i]:
return False
return True
def get_tuples(mydict,target):
keys = filter(lambda x: match(x,target),mydict.keys())
return [mydict[key] for key in keys]
#example:
dict= { (1,3,5):(1,2,3),
(1,3,6):(1,5,7),
(1,2,5):(1,4,5),
}
print get_tuples(dict,(1,3,'*'))
。
答案 3 :(得分:0)
@AshwiniChaudhary's solution可以轻松地应用于面向对象的解决方案。您可以继承dict
并添加一个方法:
class tup_dict(dict):
def getitems_fromtup(self, key):
for k, v in self.items():
if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)):
yield v
d = tup_dict({("foo", 4 , "q"): 9,
("foo", 4 , "r"): 8,
("foo", 8 , "s"): 7,
("bar", 15, "t"): 6,
("bar", 16, "u"): 5,
("baz", 23, "v"): 4})
res = list(d.getitems_fromtup(("foo", 4, None))) # [9, 8]