If instead of key2 in key (that is, " key2 is a substring of key "), you change your requirement that " key2 is the key prefix" (as your examples demonstrate), you can use trie to effectively check the prefix. See this answer .
First define make_trie , as in the answer above:
_end = '_end_' def make_trie(*words): root = dict() for word in words: current_dict = root for letter in word: current_dict = current_dict.setdefault(letter, {}) current_dict = current_dict.setdefault(_end, _end) return root
Then define a function similar to in_trie from the above answer, but checking if the key is a strict prefix of the other key:
def is_strict_prefix_of_word_in_trie(trie, word): current_dict = trie for letter in word: if letter in current_dict: current_dict = current_dict[letter] else: return False else: if _end in current_dict: return False
Finally, complete your deletions like this:
def reduce_dict(dictionary): trie = make_trie(dictionary.keys()) reduced = dictionary.copy() for key in dictionary: if is_strict_prefix_of_word_in_trie(trie, key): reduced.pop(key, 0) return reduced
Or you can use dictionary comprehension:
def reduce_dict(dictionary): trie = make_trie(dictionary.keys()) return {key: value for (key, value) in dictionary \ if not is_strict_prefix_of_word_in_trie(trie, key)}
source share