在Python中,如何将字符串与字典项匹配(例如'Bra *')

时间:2018-12-27 11:28:57

标签: python dictionary

我是Python的新手,请原谅我问一些愚蠢的事情。 从文本文件中,将字典用作通过/阻止过滤器。 文本文件包含地址和一个块或一个允许的名称,例如“ 002029568,allow”或“ 0011 *,allow”(不带引号)。 搜索输入是带有完整代码的字符串,例如“ 001180000”。 如何评估搜索项是否在词典中并使其与“ 0011 *,allow”行匹配? 非常感谢您的努力!

过滤器词典的制作方法是:

def loadFilterDict(filename):
global filterDict
try:
    with open(filename, "r") as text_file:
        lines = text_file.readlines()
        for s in lines:
            fields = s.split(',')
            if len(fields) == 2:
                filterDict[fields[0]] = fields[1].strip()
    text_file.close()
except:
    pass

检查代码(ccode)是否在字典中:

    if ccode in filterDict:                   
                if filterDict[ccode] in ['block']:
                    continue
            else:
                if filterstat in ['block']:
                    continue

过滤器文件如下:

002029568,允许 000923993,允许 0011 *,允许

2 个答案:

答案 0 :(得分:2)

如果文件中的通配符条目具有固定长度(例如,您只需要支持0011*,allow之类的行,而无需支持00110*,allow0*,allow之类的行或任何其他任意数字位数紧跟*之后),您可以使用嵌套字典,其中外键是通配符条目的已知部分。

d = {'0011': {'001180000': 'value', '001180001': 'value'}}

然后,当您解析文件并到达行0011*,allow时,您无需进行任何匹配。您要做的就是检查'0011'是否存在。粗暴的例子:

d = {'0011': {'001180000': 'value', '001180001': 'value'}}

line = '0011*,allow'
prefix = line.split(',')[0][:-1]
if prefix in d:
    # there is a "match", then you can deal with all the entries that match,
    # in this case the items in the inner dictionary
    # {'001180000': 'value', '001180001': 'value'}
    print('match')
else:
    print('no match')

如果您确实需要支持任意长度的通配符条目,则必须诉诸循环遍历字典(因此击败使用字典开头的点):

d = {'001180000': 'value', '001180001': 'value'}

line = '0011*,allow'
prefix = line.split(',')[0][:-1]
for k, v in d.items():
    if k.startswith(prefix):
        # found matching key-value pair
        print(k, v)

答案 1 :(得分:2)

如果您可以使用re,则不必担心通配符,而让re.match为您完成艰苦的工作:

# Rules input (this could also be read from file)
lines = """002029568,allow
0011*,allow
001180001,block
"""

# Parse rules from string
rules = []
for line in lines.split("\n"):
    line = line.strip()
    if not line:
        continue
    identifier, ruling = line.split(",")
    rules += [(identifier, ruling)]

# Get rulings for specific number
def rule(number):
    from re import match
    rulings = []
    for identifier, ruling in rules:
        # Replace wildcard with regex .*
        identifier = identifier.replace("*", ".*")
        if match(identifier, number):
            rulings += [ruling]
    return rulings

print(rule("001180000"))
print(rule("001180001"))

哪些印刷品:

['allow']
['allow', 'block']

该函数将返回规则列表。它们的顺序与配置行中显示的顺序相同。因此,您可以轻松选择最感兴趣的一项或最后一项。

或者,如果您可以假设没有两个裁定会干涉,则过早打破循环。

示例:

  • 001180000仅与0011*,allow匹配,因此唯一适用的规则是allow
  • 001180001首先与0011*,allow匹配,所以您将像以前一样获得allow。但是,它也与001180001,block相匹配,因此block也将添加到规则中。