Python正则解析游戏货币字符串的求和问题及优化咨询
游戏货币转换器开发问题
我正在为一款游戏开发Python货币转换器,需要解析给定字符串中的各类货币数量,并统一折算为最小面额(便士)。
示例输入:"5 royals 10 dollars 35 pennies",解析后预期结果为:matches.group(2) == 5,matches.group(4) == 10,matches.group(7) == 35。
目前使用以下正则表达式可以正常匹配:
import re matches = re.search(r"(?:(\d+) crowns)?(?:(\d+) royals)?(?:(\d+) ten-dollars)?(?:(\d+) dollars)?(?:(\d+) half-dollars)?(?:(\d+) ten-pence)?(?:(\d+) pennies)?", string, re.IGNORECASE)
但在计算总便士数时遇到两个问题:
- 直接计算会因不存在的匹配项返回
None,触发TypeError; - 尝试逐个判断累加时,仅最后一个面额的数量被计入,其余均被忽略。
现咨询:
- 有没有更优的方法处理部分匹配项存在的情况?
- 为何if语句仅累加最后一项,该如何修复?
问题1:更优的部分匹配处理方案
方案1:使用findall批量捕获(推荐)
放弃固定顺序的search,改用findall匹配所有(数量+货币)对,再通过字典映射兑换比例计算总和。这种方法不依赖输入中货币的顺序,代码更简洁健壮:
import re # 定义各货币到便士的兑换比例(根据游戏实际设定调整) CURRENCY_RATES = { 'crowns': 500, 'royals': 100, 'ten-dollars': 1000, 'dollars': 100, 'half-dollars': 50, 'ten-pence': 10, 'pennies': 1 } def convert_to_pennies(string): # 匹配所有数字+货币的组合,忽略大小写 matches = re.findall(r"(\d+)\s+([a-z-]+)", string, re.IGNORECASE) total = 0 for amount_str, currency in matches: currency_lower = currency.lower() if currency_lower in CURRENCY_RATES: total += int(amount_str) * CURRENCY_RATES[currency_lower] return total # 测试示例 print(convert_to_pennies("5 royals 10 dollars 35 pennies")) # 输出:1535
方案2:处理search返回的None值
如果坚持使用原正则,可以通过or 0将None转为0,避免TypeError:
def convert_with_search(string): pattern = r"(?:(\d+) crowns)?(?:(\d+) royals)?(?:(\d+) ten-dollars)?(?:(\d+) dollars)?(?:(\d+) half-dollars)?(?:(\d+) ten-pence)?(?:(\d+) pennies)?" matches = re.search(pattern, string, re.IGNORECASE) # 逐个获取分组,None则转为0 crowns = int(matches.group(1) or 0) royals = int(matches.group(2) or 0) ten_dollars = int(matches.group(3) or 0) dollars = int(matches.group(4) or 0) half_dollars = int(matches.group(5) or 0) ten_pence = int(matches.group(6) or 0) pennies = int(matches.group(7) or 0) # 计算总和 total = (crowns * 500) + (royals * 100) + (ten_dollars * 1000) + (dollars * 100) + (half_dollars *50) + (ten_pence *10) + pennies return total
问题2:if语句仅累加最后一项的原因及修复
核心原因
- 正则顺序限制:你的原正则是按固定顺序匹配的,只有当输入字符串中的货币顺序和正则里的顺序(crowns→royals→ten-dollars→dollars→...)完全一致时,才能正确捕获所有分组。如果输入顺序混乱,前面的分组会因匹配位置已过而返回
None。 - 条件语句错误:如果代码中误用了
elif而非多个独立的if,会导致只有第一个匹配的项被累加,后续判断被跳过。
修复方案
- 改用
findall方案(推荐):如问题1的方案1,完全不依赖输入顺序,自动捕获所有出现的货币。 - 修正条件语句逻辑:确保使用多个独立的
if而非elif,示例如下:# 错误示例(用elif会导致仅第一个匹配项被累加) total = 0 if matches.group(1): total += int(matches.group(1)) * 500 elif matches.group(2): total += int(matches.group(2)) * 100 # 正确示例(用多个if,每个匹配项都会被判断累加) total = 0 if matches.group(1): total += int(matches.group(1)) * 500 if matches.group(2): total += int(matches.group(2)) * 100 # 依次处理所有分组
内容的提问来源于stack exchange,提问作者edhil
相关产品推荐
相关产品推荐

