字典键上的正则表达式匹配

时间:2016-02-19 13:24:11

标签: python regex dictionary key normalization

想象一下,我们有一本字典:{'Hello World': value1, 'Testing': value2}

现在我们需要在字典中查找一个单词。密钥K需要完全匹配“Hello World'或者'测试',使用。

所以,让我们的text = 'hello world'我们仍然希望这返回value1

那么我们如何处理文本与键的正则表达式匹配?理想情况下,我们不想迭代字典

编辑:间距方面只是一个简单的例子。文本可能会更改,以及我们想要匹配的数字和字母的组合。我们通常会使用正则表达式

4 个答案:

答案 0 :(得分:2)

你正在做的事情几乎击败了dict的效率,所以你最好自己创建自己的dict类课程。这是一个简单的例子:

from re import search, I

class RegexMap(object):
    def __init__(self, *args, **kwargs):
        self._items = dict(*args, **kwargs)
    def __getitem__(self, key):
        for regex in self._items.keys():
            if search(regex, key, I):
                return self._items[regex]
        raise KeyError

用法:

>>> rm = RegexMap({'\s*hello\s*world\s*':1, '\s*foo\s*bar\s*':2})
>>> rm['Hello World']
1
>>> rm['foobar']
2
>>> rm['baz']
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    rm['baz']
  File "C:\Users\dmurphy\Documents\python\_t.py", line 10, in __getitem__
    raise KeyError
KeyError
>>> 

从那里,您可以添加更多dict功能。请参阅Data Model docs

它会破坏你的#34;没有迭代&#34;条款,但如果您想要推广到正则表达式,我不确定是否有任何解决方法。

答案 1 :(得分:0)

我愿意,

>>> d = {'Hello World': 'value1', 'Testing': 'value2'}
>>> text = 'hello     world'
>>> key = next(x for x in (re.search(r'(?i)' + re.sub(r'(\s)+', r'\1', text.strip()), i) for i in d.keys()) if x).group()
>>> d[key]
'value1'

答案 2 :(得分:0)

为了帮助查找,您可以排序和平分,以找到在找到匹配项时缩小查找范围的位置,或者当前密钥是&gt;你正在寻找的东西。

from bisect import bisect_left

d = {'Hello World': "value1", 'Testing': "value2"}

items = sorted([(k.lstrip().lower(),v) for k, v in d.items()])

text = 'hello     world'
ind = bisect_left(items,(text.lower(),), hi=len(items) - 1)
# use items[ind]

或者使用每个键的前几个字母创建映射:

from collections import defaultdict
lookup_mapping = defaultdict(list)

for k in d:
    lookup_mapping[k[:2].lower().lstrip()].append(k)

poss =  lookup_mapping[text[:2].lower().lstrip()]

您可以使用正则表达式来查找匹配项,也可以通过分切,剥离等来对数据进行标准化。它完全取决于输入的外观,但通过分组,您至少可以减少必须进行的比较

答案 3 :(得分:0)

也许考虑规范你的词典中的键。使用没有分隔符的python的string.split函数将删除所有空格。

def normalize(word):
    return " ".join(word.split()).lower()
d = {'Hello World': 'value1', 'Testing': 'value2'}
d = {normalize(k): v for k, v in d.items()} 
print(d)
>>> {'hello world': 'value1', 'testing': 'value2'}
text = 'hello     world'
d[normalize(text)]
>>> 'value1'