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

Python 正则表达式可以用作字典中的键吗?,python,regex,dictionary,Python,Regex,Dictionary,我想创建一个字典,其中键是正则表达式: d = {'a.*': some_value1, 'b.*': some_value2} 然后,当我查字典时: d['apple'] 我希望苹果'apple'与正则表达式的键匹配。如果与键/正则表达式完全匹配,则应返回相应的值 例如,'apple'与正则表达式'a.*完全匹配,因此,应该返回一些值1 当然,所有这些都假设正则表达式键不冲突(即,两个键不应完全匹配同一字符串)。假设我可以在构建密钥时手动处理此需求 这在Python中可能吗?如果是这样的话

我想创建一个字典,其中键是正则表达式:

d = {'a.*': some_value1, 'b.*': some_value2}
然后,当我查字典时:

d['apple']
我希望苹果
'apple'
与正则表达式的键匹配。如果与键/正则表达式完全匹配,则应返回相应的值

例如,
'apple'
与正则表达式
'a.*
完全匹配,因此,
应该返回一些值1

当然,所有这些都假设正则表达式键不冲突(即,两个键不应完全匹配同一字符串)。假设我可以在构建密钥时手动处理此需求


这在Python中可能吗?如果是这样的话,这将是一个非常优雅和强大的构造

当然。只要像平常一样查找它们,并检查是否匹配即可

import re

def find_matches(d, item):
    for k in d:
        if re.match(k, item):
            return d[k]

d = {'a.*': 'a match', 'b.*': 'b match'}
for item in ['apple', 'beer']:
    print(find_matches(d, item))
结果:

a match
b match

请注意,
re.match
仅在表达式位于字符串开头时生成匹配。如果表达式可以位于字符串中的任何位置,请使用
re.search

您可以使用
re.compile
d模式对象作为字典键:

>>> import re
>>> regex = re.compile('a.*')
>>> d = {regex: 'foo'}
>>> d[re.compile('a.*')]
'foo'
请注意,重新编译相同的正则表达式会给您一个相等的键(事实上,相同的对象:
re.compile('a.*)是d.keys()[0]
),因此您可以取回针对它存储的任何内容

然而:

  • 正如注释中指出的,多个正则表达式可以匹配同一个字符串
  • 字典是不排序的,所以每次运行程序时,您可能会首先得到不同的匹配正则表达式;及
  • 对于给定可能匹配一个或多个
    regex
    键的字符串,没有
    O(1)
    方法向字典
    {regex:result,…}
    询问
    结果
因此,很难看出你会发现它有什么用途



如果您能想出一种方法来确保没有两个键可以匹配同一个字符串,那么您可以创建一个子类,在添加新键时应用此检查,并实现
\uuuuu getitem\uuuuu
来扫描键-值对,并返回参数与键正则表达式匹配的第一个值。同样,这将是
O(n)

Python字典被实现为-这意味着任何
mydict[myvalue]
查找通过内部散列
myvalue
都非常快。使用正则表达式作为键将取消此功能。与其使用字典,不如使用一个简单的列表或元组,其中每个项都是元组,格式为:
(模式/编译的正则表达式,值)
,并扫描它们,直到正则表达式通过。这还将使您能够处理正则表达式的顺序(例如,从特定到一般):


另请参见Django’s,了解您想法的(非常)高级实现。

可能的解决方案:

import re


class RegexDict(dict):

    def __init__(self):
        super(RegexDict, self).__init__()

    def __getitem__(self, item):
        for k, v in self.iteritems():
            if re.match(k, item):
                return v
        raise KeyError


if __name__ == '__main__':
    d = RegexDict()

    d[r'a.*'] = 'Informed a key that starts with a'
    d[r'b.*'] = 'Informed a key that starts with b'
    d[r'\w+'] = 'Informed alphanumeric as key'
    d[r'\d+'] = 'Informed numbers as key'
    d[r'\s+'] = 'Informed spaces as key'

    print d['  ']
    print d['apple']
    print d['bee']
    print d['123']
    print d['word']
    print d['word1']
Informed spaces as key
Informed a key that starts with a
Informed a key that starts with b
Informed numbers as key
Informed alphanumeric as key
Informed alphanumeric as key
输出:

import re


class RegexDict(dict):

    def __init__(self):
        super(RegexDict, self).__init__()

    def __getitem__(self, item):
        for k, v in self.iteritems():
            if re.match(k, item):
                return v
        raise KeyError


if __name__ == '__main__':
    d = RegexDict()

    d[r'a.*'] = 'Informed a key that starts with a'
    d[r'b.*'] = 'Informed a key that starts with b'
    d[r'\w+'] = 'Informed alphanumeric as key'
    d[r'\d+'] = 'Informed numbers as key'
    d[r'\s+'] = 'Informed spaces as key'

    print d['  ']
    print d['apple']
    print d['bee']
    print d['123']
    print d['word']
    print d['word1']
Informed spaces as key
Informed a key that starts with a
Informed a key that starts with b
Informed numbers as key
Informed alphanumeric as key
Informed alphanumeric as key

你可以用这个。它对我有用。您需要确保您的密钥是唯一的

word_mapping = {
    r'\W*J\W*2\W*W\W*' : ' j2w ', r'\W*power\W*on\W*': ' poweron ', 
    r'\W*Some From Dase [0-9]*\W*' : ''
}

def correct_word_mapping(x, dic):
    for word in dic.keys():
        #if word in x:
        x = re.sub(word, dic[word], x, flags=re.IGNORECASE)
return x 

print(correct_word_mapping("power on J 2 w PowerONJ2 w", word_mapping))

“如果是这样,它将是一个非常优雅/强大的构造!”-不,它不会是,因为您可以编写无限数量的正则表达式来匹配同一字符串。你问的问题不对。请解释你想解决的问题。你想要两个不相容的东西。如果不同时查看正则表达式和字符串,程序就无法确定正则表达式是否与字符串匹配。给定一组正则表达式(键)和一个字符串,知道哪个正则表达式与该字符串匹配的唯一方法是尝试每个正则表达式。但是字典的性能完全取决于它在不必遍历所有键的情况下找到匹配键的能力。因此,即使您可以避免密钥中的所有歧义,性能也不会比一组键值对更好。很好,谢谢!我建议在找到匹配项后在循环中使用
break
,而不是在函数中使用两个
return
语句。然后在最后返回存储的值。