partial match dictionary key(of tuples) in python












6















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.










share|improve this question




















  • 2





    do you also need to support get(f,*,h) returning tuple3?

    – Foon
    Sep 19 '13 at 11:46











  • not in the current version, but that would also be great

    – Aavaas
    Sep 19 '13 at 11:48













  • Notes: (1:2:3) causes a SyntaxError, and it's generally not a good idea to name variables after builtins, such as tuple and dict.

    – user707650
    Sep 19 '13 at 12:03











  • sorry I meant (1,2,3) and dict and tuple was to show the idea

    – Aavaas
    Sep 19 '13 at 12:24
















6















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.










share|improve this question




















  • 2





    do you also need to support get(f,*,h) returning tuple3?

    – Foon
    Sep 19 '13 at 11:46











  • not in the current version, but that would also be great

    – Aavaas
    Sep 19 '13 at 11:48













  • Notes: (1:2:3) causes a SyntaxError, and it's generally not a good idea to name variables after builtins, such as tuple and dict.

    – user707650
    Sep 19 '13 at 12:03











  • sorry I meant (1,2,3) and dict and tuple was to show the idea

    – Aavaas
    Sep 19 '13 at 12:24














6












6








6


4






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.










share|improve this question
















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.







python python-2.7 dictionary






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 19 '13 at 12:22







Aavaas

















asked Sep 19 '13 at 11:39









AavaasAavaas

347414




347414








  • 2





    do you also need to support get(f,*,h) returning tuple3?

    – Foon
    Sep 19 '13 at 11:46











  • not in the current version, but that would also be great

    – Aavaas
    Sep 19 '13 at 11:48













  • Notes: (1:2:3) causes a SyntaxError, and it's generally not a good idea to name variables after builtins, such as tuple and dict.

    – user707650
    Sep 19 '13 at 12:03











  • sorry I meant (1,2,3) and dict and tuple was to show the idea

    – Aavaas
    Sep 19 '13 at 12:24














  • 2





    do you also need to support get(f,*,h) returning tuple3?

    – Foon
    Sep 19 '13 at 11:46











  • not in the current version, but that would also be great

    – Aavaas
    Sep 19 '13 at 11:48













  • Notes: (1:2:3) causes a SyntaxError, and it's generally not a good idea to name variables after builtins, such as tuple and dict.

    – user707650
    Sep 19 '13 at 12:03











  • sorry I meant (1,2,3) and dict and tuple was to show the idea

    – Aavaas
    Sep 19 '13 at 12:24








2




2





do you also need to support get(f,*,h) returning tuple3?

– Foon
Sep 19 '13 at 11:46





do you also need to support get(f,*,h) returning tuple3?

– Foon
Sep 19 '13 at 11:46













not in the current version, but that would also be great

– Aavaas
Sep 19 '13 at 11:48







not in the current version, but that would also be great

– Aavaas
Sep 19 '13 at 11:48















Notes: (1:2:3) causes a SyntaxError, and it's generally not a good idea to name variables after builtins, such as tuple and dict.

– user707650
Sep 19 '13 at 12:03





Notes: (1:2:3) causes a SyntaxError, and it's generally not a good idea to name variables after builtins, such as tuple and dict.

– user707650
Sep 19 '13 at 12:03













sorry I meant (1,2,3) and dict and tuple was to show the idea

– Aavaas
Sep 19 '13 at 12:24





sorry I meant (1,2,3) and dict and tuple was to show the idea

– Aavaas
Sep 19 '13 at 12:24












4 Answers
4






active

oldest

votes


















8














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]





share|improve this answer


























  • if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

    – Aavaas
    Sep 19 '13 at 12:14











  • @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

    – Ashwini Chaudhary
    Sep 19 '13 at 12:32











  • so this is more simple then, thank you!

    – Aavaas
    Sep 19 '13 at 12:52











  • In Python 3.x , .iteritems() is replaced with .items()

    – lacrima
    7 hours ago



















4














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.






share|improve this answer
























  • This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

    – Jacob
    Sep 19 '13 at 12:37





















1














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,'*'))


.






share|improve this answer
























  • This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

    – Jacob
    Sep 19 '13 at 12:51











  • I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

    – Aavaas
    Sep 19 '13 at 12:56



















0














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



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]





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f18893624%2fpartial-match-dictionary-keyof-tuples-in-python%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    8














    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]





    share|improve this answer


























    • if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

      – Aavaas
      Sep 19 '13 at 12:14











    • @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

      – Ashwini Chaudhary
      Sep 19 '13 at 12:32











    • so this is more simple then, thank you!

      – Aavaas
      Sep 19 '13 at 12:52











    • In Python 3.x , .iteritems() is replaced with .items()

      – lacrima
      7 hours ago
















    8














    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]





    share|improve this answer


























    • if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

      – Aavaas
      Sep 19 '13 at 12:14











    • @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

      – Ashwini Chaudhary
      Sep 19 '13 at 12:32











    • so this is more simple then, thank you!

      – Aavaas
      Sep 19 '13 at 12:52











    • In Python 3.x , .iteritems() is replaced with .items()

      – lacrima
      7 hours ago














    8












    8








    8







    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]





    share|improve this answer















    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]






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Sep 19 '13 at 12:18

























    answered Sep 19 '13 at 12:01









    Ashwini ChaudharyAshwini Chaudhary

    179k35325391




    179k35325391













    • if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

      – Aavaas
      Sep 19 '13 at 12:14











    • @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

      – Ashwini Chaudhary
      Sep 19 '13 at 12:32











    • so this is more simple then, thank you!

      – Aavaas
      Sep 19 '13 at 12:52











    • In Python 3.x , .iteritems() is replaced with .items()

      – lacrima
      7 hours ago



















    • if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

      – Aavaas
      Sep 19 '13 at 12:14











    • @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

      – Ashwini Chaudhary
      Sep 19 '13 at 12:32











    • so this is more simple then, thank you!

      – Aavaas
      Sep 19 '13 at 12:52











    • In Python 3.x , .iteritems() is replaced with .items()

      – lacrima
      7 hours ago

















    if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

    – Aavaas
    Sep 19 '13 at 12:14





    if all(k1 == k2 or k2 is None for k1, k2 in zip(k, key)): yield v "wow this is some mind bending line"

    – Aavaas
    Sep 19 '13 at 12:14













    @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

    – Ashwini Chaudhary
    Sep 19 '13 at 12:32





    @TheAvs all() will return True if all items satisfied the condition k1 == k2 or k2 is None, and zip() returns items on the same index from both iterables. yield is used to make a generator function.

    – Ashwini Chaudhary
    Sep 19 '13 at 12:32













    so this is more simple then, thank you!

    – Aavaas
    Sep 19 '13 at 12:52





    so this is more simple then, thank you!

    – Aavaas
    Sep 19 '13 at 12:52













    In Python 3.x , .iteritems() is replaced with .items()

    – lacrima
    7 hours ago





    In Python 3.x , .iteritems() is replaced with .items()

    – lacrima
    7 hours ago













    4














    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.






    share|improve this answer
























    • This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

      – Jacob
      Sep 19 '13 at 12:37


















    4














    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.






    share|improve this answer
























    • This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

      – Jacob
      Sep 19 '13 at 12:37
















    4












    4








    4







    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.






    share|improve this answer













    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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 19 '13 at 12:08









    KevinKevin

    59.6k1169114




    59.6k1169114













    • This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

      – Jacob
      Sep 19 '13 at 12:37





















    • This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

      – Jacob
      Sep 19 '13 at 12:37



















    This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

    – Jacob
    Sep 19 '13 at 12:37







    This is the only one so far with sublinear lookup times. +1 and this data structure can be used to look in any position, with an accessor function.

    – Jacob
    Sep 19 '13 at 12:37













    1














    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,'*'))


    .






    share|improve this answer
























    • This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

      – Jacob
      Sep 19 '13 at 12:51











    • I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

      – Aavaas
      Sep 19 '13 at 12:56
















    1














    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,'*'))


    .






    share|improve this answer
























    • This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

      – Jacob
      Sep 19 '13 at 12:51











    • I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

      – Aavaas
      Sep 19 '13 at 12:56














    1












    1








    1







    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,'*'))


    .






    share|improve this answer













    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,'*'))


    .







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 19 '13 at 12:00









    FoonFoon

    4,63492736




    4,63492736













    • This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

      – Jacob
      Sep 19 '13 at 12:51











    • I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

      – Aavaas
      Sep 19 '13 at 12:56



















    • This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

      – Jacob
      Sep 19 '13 at 12:51











    • I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

      – Aavaas
      Sep 19 '13 at 12:56

















    This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

    – Jacob
    Sep 19 '13 at 12:51





    This correctly answers the question, but with O(n). The point of a dict is to get O(1) lookup. Just a heads up the wildcard search will be slow compared to a lookup. If convenient for the rest of your code use a better data structure for wildcard search.

    – Jacob
    Sep 19 '13 at 12:51













    I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

    – Aavaas
    Sep 19 '13 at 12:56





    I have timed your function and it performs constantly slower than the implementation by @hcwhsa by about 0.012 seconds for a dictionary of about 10,000 elements. And thank you very much for quick answer.

    – Aavaas
    Sep 19 '13 at 12:56











    0














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



    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]





    share|improve this answer




























      0














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



      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]





      share|improve this answer


























        0












        0








        0







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



        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]





        share|improve this answer













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



        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]






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 26 '18 at 9:40









        jppjpp

        102k2165116




        102k2165116






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f18893624%2fpartial-match-dictionary-keyof-tuples-in-python%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Ottavio Pratesi

            Tricia Helfer

            15 giugno