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

Posted

技术标签:

【中文标题】字典键上的正则表达式匹配【英文标题】:Regex matching on dictionary keys 【发布时间】:2016-06-01 02:12:50 【问题描述】:

假设我们有一本字典:'Hello World': value1, 'Testing': value2

现在我们需要在字典中查找一个单词。密钥 K 需要与“Hello World”或“Testing”完全匹配才能使用。

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

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

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

【问题讨论】:

使用" ".join(text.split()).title()? 谢谢,但是更复杂的正则表达式模式呢?这可能不仅仅是间距问题 请在您的问题中至少添加一个预期的输入/输出...我不确定您到底需要什么...! 有点完全违背了使用字典的目的,你的数据来自哪里? 你的问题很不清楚。您应该提供更多输入和所需输出的示例,否则 zondo 的评论会回答您的问题。 【参考方案1】:

也许考虑规范化你的字典中的键。使用不带分隔符的 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'

【讨论】:

如果你有"cat dog""catd og"这两个字怎么办? 这些都将被规范化为“catdog” 这是我的观点,您的解决方案不起作用。如果您的原始字典是d = "Cat Dog": "value1", "Catd Og": "value2",那么您只会丢失其中一个。 啊,我明白了,最好在连接中使用空格:d = " ".join(k.split()).lower(): v for k, v in d.items () 这将留下: d = 'cat dog': 'value1', 'catd og': 'value2'【参考方案2】:

你正在做的几乎是在击败dicts 的效率,所以你最好制作自己的dict-like 类。这是一个简单的例子:

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。

它确实打破了你的“无迭代”条款,但如果你想推广到正则表达式,我不确定有什么办法。

【讨论】:

也许是因为 OP 说他不想遍历键,而您的解决方案正是这样做的?但我同意在他的案例中似乎没有办法绕过某种迭代。 @gill 很公平,我读了 3 次都错过了。不过,他确实说“理想”,我不确定是否有办法解决。 他确实做到了。但看起来如果 OP 没有这个(我认为)无法达到的理想,那么我们就不会有这个问题。附言。我没有对你投反对票:) @gill 哦,我知道。如果不立即发表评论,投反对票的人不会留下来解释自己。 ^^ 感谢所有意见,但请不要假设我是男性。【参考方案3】:

为了帮助查找,您可以排序和平分查找从哪里开始查找以缩小查找范围,当您找到匹配项或当前键是 > 您正在查找的内容时。

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()]

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

【讨论】:

【参考方案4】:

我愿意,

>>> 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'

【讨论】:

以上是关于字典键上的正则表达式匹配的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式可以用作字典中的键吗?

为啥 Windows 上的 git commit-msg 与正则表达式不匹配

PHP正则表达式匹配网页里的音标,会的进来帮忙搞定

正则表达式字符匹配

使用正则表达式从对象中检索值 - JS [关闭]

正则表达式以啥结尾