trotta
trotta

Reputation: 1226

Compare list with dictionary (that contains wildcards), return values

I have a list that contains several strings and a dictionary with strings (that contain wildcards) as keys and integers as values.

For example like this:

list1 = ['i', 'like', 'tomatoes']
dict1 = {'tomato*':'3', 'shirt*':'7', 'snowboard*':'1'}

I would like to go through list1 and see if there is a key in dict1 that (with the wildcard) matches the string from list1 and get the respective value from dict1. So in this case 3 for 'tomato*'.

Is there a way to iterate over list1, see if one of the dict1 keys (with wildcards) matches with this particular string and return the value from dict1?

I know I could iterate over dict1 and compare the keys with the elements in list1 this way. But in my case, the dict is very large and in addition, I have a lot of lists to go through. So it would take too much time to loop through the dictionary every time. I thought about turning the keys into a list as well and get wildcard matches with a list comprehension and fnmatch(), but the returned match wouldn't be able to find the value in the dict (because of the wildcard).

Upvotes: 0

Views: 297

Answers (1)

hyloop
hyloop

Reputation: 359

Here is a data structure implemented using default python package to help you.

from collections import defaultdict


class Trie(defaultdict):
    def __init__(self, value=None):
        super().__init__(lambda: Trie(value))  # Trie is essentially hash-table within hash-table
        self.__value = value

    def __getitem__(self, key):
        node = self
        if len(key) > 1:  # allows you to access the trie like this trie["abc"] instead of trie["a"]["b"]["c"]
            for char in key:
                node = node[char]
            return node
        else:  # actual getitem routine
            return defaultdict.__getitem__(self, key)

    def __setitem__(self, key, value):
        node = self
        if len(key) > 1:  # allows you to access the trie like this trie["abc"] instead of trie["a"]["b"]["c"]
            for char in key[:-1]:
                node = node[char]
            node[key[-1]] = value
        else:  # actual setitem routine
            if type(value) is int:
                value = Trie(int(value))
            defaultdict.__setitem__(self, key, value)

    def __str__(self):
        return str(self.__value)

d = Trie()
d["ab"] = 3
print(d["abcde"])

3

Upvotes: 1

Related Questions