【问题标题】:Searching for a pattern in dictionary keys在字典键中搜索模式
【发布时间】:2020-04-30 10:38:50
【问题描述】:

我想用一些给定的模式搜索 python 字典键。这更像是子字符串搜索,但具有 char 级别。下面的代码工作正常,但我需要一些调整,因为当我们有数千个键时它会出现性能问题。哈希键具有排序的字母。通过键的字母排序,我的意思是字典的每个键(单词)本身都是排序的,而不是根据键排序的整个字典。即密钥可以是aaklm,而不是kamal

另外,这个搜索部分是否有任何外部库/API?

import re

def getKey(str, list):
    expr = re.compile(str)
    return [elem for elem in list if expr.match(elem)]


wordDict = {'AADFLORW':['value1'], 'AAAGRU': ['VAL1', 'SOME DIFFERENT VALUE']}
m = re.compile(u'[a-zA-Z]').findall('ADOLF')    # I'm searching ADOLF in the keys
pat = '.*' + '(.*)'.join(sorted(m)) + '.*'

for key in getKey(pat, wordDict.keys()):
    print(key)

【问题讨论】:

  • stackoverflow.com/questions/10795973/… 这应该会有所帮助
  • 如果键是按字母顺序排列的,它们怎么能包含'adolf'?
  • @Junuxx ADOLF 是输入,我也在对输入进行排序,然后检查哈希。

标签: python python-3.x dictionary substring


【解决方案1】:

就像现在一样,搜索的主要部分将是检查wordDict 中的每个键与模式。我能想到的一种优化是减少这种搜索。

首先我构建“元”字典,其中键是 frozenset 的字符 wordDict 的键和值是 wordDict 键的列表。

getKey() 中,使用这个元字典,我只检查可能匹配的键(所以不是所有键)。

import re
from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

def getKey(string, pat, meta):
    k = ''.join(sorted(set(string)))
    expr = re.compile(pat)
    return [elem for elem in meta[frozenset(k)] if expr.match(elem)] # <--- here I search only valid keys (keys where there's possibility of match)

wordDict = {'AADFLORW':['value1'], 'AAAGRU': ['VAL1', 'SOME DIFFERENT VALUE']}

# build meta information about wordDict.keys()
# This could take a while!!!
meta = {}
for k in wordDict.keys():
    for p in powerset(set(k)):
        if p:
            meta.setdefault(frozenset(p), []).append(k)

# from pprint import pprint
# pprint(meta)

m = re.compile(r'[a-zA-Z]').findall('ADOLF')    # I'm searching ADOLF in the keys
pat = '.*' + '(.*)'.join(sorted(m)) + '.*'

for key in getKey('ADOLF', pat, meta):
    print(key)

打印:

ADFLORW

为了说明,“元”字典现在看起来像这样:

{frozenset({'A'}): ['AADFLORW', 'AAAGRU'],
 frozenset({'D'}): ['AADFLORW'],
 frozenset({'L'}): ['AADFLORW'],
 frozenset({'R'}): ['AADFLORW', 'AAAGRU'],
 frozenset({'W'}): ['AADFLORW'],
 frozenset({'O'}): ['AADFLORW'],
 frozenset({'F'}): ['AADFLORW'],
 frozenset({'A', 'D'}): ['AADFLORW'],
 frozenset({'A', 'L'}): ['AADFLORW'],
 frozenset({'A', 'R'}): ['AADFLORW', 'AAAGRU'],
 frozenset({'W', 'A'}): ['AADFLORW'],

...

它可能相当大,所以现在你正在用“空间”换取“速度”。

【讨论】:

    猜你喜欢
    • 2016-07-26
    • 2014-08-01
    • 2011-07-07
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-05
    • 2017-11-11
    相关资源
    最近更新 更多