我想创建一个字典,其中键是正则表达式:
d = {'a.*': some_value1, 'b.*': some_value2}
然后,当我查看字典时:
d['apple']
我希望将apple 'apple'
与正则表达式的键匹配。如果与key / regular-expression完全匹配,则应返回相应的值。
例如,'apple'
完全匹配正则表达式'a.*'
,因此,应返回some_value1
。
当然,所有这些都假定正则表达式键不冲突(即两个键不应该完全匹配相同的字符串)。假设在构建密钥时我可以手动处理这个要求。
这在Python中可行吗?如果是这样,它将是一个非常优雅和强大的结构!
答案 0 :(得分:10)
Python字典实现为hash tables - 这意味着通过内部散列mydict[myvalue]
,任何myvalue
查找都非常快。使用正则表达式作为键将取消此功能。您应该使用简单的列表或元组,而不是使用字典,其中每个项目都是格式为(pattern/compiled regular expression, value)
的元组,并扫描它们直到正则表达式通过。这也使您能够使用正则表达式的顺序(例如,从特定表达式到通用表达式):
import re
LOOKUPS = [
('a.*', 'a'),
('b.*', 'b'),
]
def lookup(s, lookups):
for pattern, value in lookups:
if re.search(pattern, s):
return value
return None
print(lookup("apple", LOOKUPS))
另请参阅Django的url resolver以了解(非常)高级实现您的想法。
答案 1 :(得分:4)
您可以使用re.compile
d模式对象作为字典键:
>>> import re
>>> regex = re.compile('a.*')
>>> d = {regex: 'foo'}
>>> d[re.compile('a.*')]
'foo'
请注意,重新编译相同的正则表达式会为您提供相同的键(同一个对象,实际上是re.compile('a.*') is d.keys()[0]
),因此您可以取回存储的任何内容。
然而:
O(1)
键匹配的情况下,没有{regex: result, ...}
方式向字典result
询问regex
值。 因此很难看出你为此找到了什么效用。
如果可以想出一种方法来确保没有两个键可以匹配相同的字符串,那么您可以创建一个MutableMapping
子类,在您添加新键时应用此检查实现__getitem__
来扫描键值对并返回参数与键正则表达式匹配的第一个值。但同样,这将是O(n)
。
答案 2 :(得分:1)
不确定。只需正常查看它们并检查匹配。
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
。
答案 3 :(得分:1)
可能的解决方案:
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
答案 4 :(得分:1)
您可以使用它。这个对我有用。您需要确保您的密钥是唯一的。
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))