重新分组:是否可以指定值类型?

时间:2019-11-13 11:16:47

标签: python regex

我有以下正则表达式分解子元素中的Tire规格,需要将其作为dict返回。其数字元素需要以int形式返回。

这是一个输入示例:

tyre_specs = '255/45W17'

所需的输出:

tyre_details = {'width': 255, 'profile': 45, 'rating': 'W', 'rim': 17}

我使用带有命名捕获的正则表达式模式捕获每个元素,这些命名匹配所需的输出字典键。然后,我使用groupdict生成我的输出字典。但是,所有值都是字符串。因此,我需要进一步处理相关值以将其转换为int。

我的功能(见下文)有效。但是我想知道是否有更好的方法可以做到这一点。例如,是否有一种方法可以强制某些特定匹配组的类型?

如果不是,这种方法是否“ pythonic”?

这是我的职能

import re

def tyre_details(tyre_size):
    pattern = r'(?P<width>\d{3})\/(?P<profile>\d{2})(?P<rating>[A-Z]{1,2})(?P<rim>\d{2})'
    try:
        details = re.match(pattern, tyre_size).groupdict()
    except AttributeError:
        raise ValueError('Input does not conform to the usual tyre size nomenclature "Width/ProfileRatingRim"')

    int_keys = set('width profile rim'.split())
    for key in int_keys:
        details[key] = int(details[key])
    return details

编辑:

  1. 添加了输入字符串不匹配时的处理异常。我将此作为值错误提出
  2. 定义了要转换为集合而不是列表的键。
  3. 删除了多余的try / except子句。

1 个答案:

答案 0 :(得分:3)

我将首先检查正则表达式是否匹配。如果确实如此,那么match.groups()可以直接取消引用到变量中,并用于构建最终的字典对象:

import re

def tyre_details(tyre_size):
    pattern  = r'(\d{3})/(\d{2})([A-Z]{1,2})(\d{2})'
    m = re.match(pattern, tyre_size)
    details = {}
    if m:
        width, profile, rating, rim = m.groups()
        details = {"width": int(width), "profile": int(profile), "rating": rating, "rim": int(rim)}
    return details

tyre_specs = '255/45W17'
print( tyre_details(tyre_specs) )
# => {'width': 255, 'profile': 45, 'rating': 'W', 'rim': 17}

请参见Python demo

使用这种方法无需命名组,并且在将try/except强制转换为str时,您不需要进行任何int或其他检查,因为相关的组仅匹配数字,参见(\d{3})(\d{2})(\d{2})

如果您需要完整的字符串匹配项,请将re.match替换为re.fullmatch,如果匹配项可以出现在字符串中的任何位置,请使用re.search

注意/不是任何特殊的正则表达式元字符,请不要在模式中将其转义。