Skip to content Skip to sidebar Skip to footer

Partial Match Dictionary Key(of Tuples) In Python

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, .

Solution 1:

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)}
defpartial_match(key, d):
    for k, v in d.iteritems():
        ifall(k1 == k2 or k2 isNonefor k1, k2 inzip(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]

Solution 2:

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.

Solution 3:

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)

defmatch(tup,target):
   iflen(tup) != len(target):
      returnFalsefor i in xrange(len(tup)):
      if target[i] != "*"and tup[i] != target[i]:
         returnFalsereturnTruedefget_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,'*'))

.

Solution 4:

@AshwiniChaudhary's solution can be trivially adapted for an object-oriented solution. You can subclass dict and add a method:

classtup_dict(dict):
    defgetitems_fromtup(self, key):
        for k, v in self.items():
            ifall(k1 == k2 or k2 isNonefor k1, k2 inzip(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]

Post a Comment for "Partial Match Dictionary Key(of Tuples) In Python"