I have a dictionary that maps 3tuple to 3tuple where key-tuples have some element in common
dict= { (a,b,c):(1,2,3),
(a,b,d):tuple1,
(a,e,b):tuple,
.
(f,g,h):tuple3,
.
.
.
tuple:tuple
}
now how can I find the values that match to (a,b,anyX) in a dictionary ie (1:2:3) and tuple1
this is computer generated and very large thus, it takes effort to determine anyX.
so, any good ways I can do this?
edit:partial matching of (f,g,*),(f, *,g) to tuple3 will also be helpful but not necessary.
A tuple can never be used as a key in a dictionary.
Because tuples are hashable and lists are not, if we want to create a composite key to use in a dictionary we must use a tuple as the key. Write code to create a dictionary called 'd1', and in it give the tuple (1, 'a') a value of “tuple”.
Duplicate keys are not allowed. A dictionary maps each key to a corresponding value, so it doesn't make sense to map a particular key more than once.
General Idea: In Python, if we want a dictionary to have multiple values for a single key, we need to store these values in their own container within the dictionary. To do so, we need to use a container as a value and add our multiple values to that container.
Lets say if you're passing None
for the missing keys then you can use all
and 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]
You could reconstruct your dictionary into a triply nested dict.
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
Here, d
is equivalent to:
d = {
"foo": {
4:{
"q": 9,
"r": 8
},
8:{
"s": 7
}
},
"bar":{
15:{
"t": 6
}
16:{
"u": 5
}
},
"baz":{
23{
"v": 4
}
}
}
Now you can easily iterate through the possible third keys, given the first and second.
#find all keys whose first two elements are "foo" and 4
a = "foo"
b = 4
for c in d[a][b].iterkeys():
print c
Result:
q
r
This only works for matching the third key. For instance, you wouldn't be able to find all second keys, given the third and the first.
There might be other ways, but assuming you just need to do a single search (in other words there might be ways to build better data structures for repeated searching): (Note that this handles arbitrary lengthed tuple's with the '*' in multiple possible locations)
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,'*'))
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With