You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

但在计算总便士数时遇到两个问题:

  1. 直接计算会因不存在的匹配项返回None,触发TypeError;
  2. 尝试逐个判断累加时,仅最后一个面额的数量被计入,其余均被忽略。

现咨询:

  1. 有没有更优的方法处理部分匹配项存在的情况?
  2. 为何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语句仅累加最后一项的原因及修复

核心原因

  1. 正则顺序限制:你的原正则是按固定顺序匹配的,只有当输入字符串中的货币顺序和正则里的顺序(crowns→royals→ten-dollars→dollars→...)完全一致时,才能正确捕获所有分组。如果输入顺序混乱,前面的分组会因匹配位置已过而返回None。
  2. 条件语句错误:如果代码中误用了elif而非多个独立的if,会导致只有第一个匹配的项被累加,后续判断被跳过。

修复方案

  1. 改用findall方案(推荐):如问题1的方案1,完全不依赖输入顺序,自动捕获所有出现的货币。
  2. 修正条件语句逻辑:确保使用多个独立的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 21:23:24