场景:工作中需要把数字、汉字、数字汉字混合的数转换为数字型。待转换的包括但不限于以下类型:”四十万零五百”,”四千八百三”, “零”, “4331”, “4百万”, “4万”, “百万”, “百”, “3万4”, “3万四”, “三万四”, “三万4”
我一开始用从前往后挨个转换,总是存在局限和问题。查找了网上的方法,大多数都是从后往前,挨着来,然后乘以单位之类的。
我想到个办法,可不跟网上那些妖艳的贱货一样。
我的暂时就叫补全法
其实仔细分析,相对于单位来说,待转换的都是简略写法,转换后的数字都是补全的写法,哪怕是零也会补全。比如说三万四,这个数字缺少了单位“千”,缺少了个十百位;但是数字“34000”就一个不少。可以总结为以下四种情况:

根据以上的情况分析,“四万零八百三”可以这样分析:

大体思路如上,具体的思路和伪码以及注释,见下面的代码:
import re
def transfer(amount: str) -> str:
"""
amount: 提取到的价格的详细数字 例如:4百(万) 百(万) 千(万)
将amount标准化为:4百(万)->400(万)
"""
# 四百三十万
unit_list = ["兆", "千亿", "百亿", "十亿", "亿", "千万", "百万", "十万", "万", "千", "百", "十", "个"]
transfer_list = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
real_amount = 0
if re.findall("^\d{1,}$", amount):
return amount
amount_unit_index = -1
unit_list_index = -1
# 找到单位列表中的起始位置,即找到数字的最大单位
for index in range(0, len(amount)):
if amount[index:index + 2] in unit_list:
amount_unit_index = index
unit_list_index = unit_list.index(amount[index:index + 2])
break
elif amount[index] in unit_list:
amount_unit_index = index
unit_list_index = unit_list.index(amount[index])
break
# 数字字符串下标从头开始
amount_unit_index = 0
amount_result = ""
# 按照单位列表的顺序找,即按照单位从大到小的顺序提取数量
for index in range(unit_list_index, len(unit_list)):
# 如果当前单位在数字字符串中,那么从上次单位结束的位置开始查找和抽取
if unit_list[index] in amount[amount_unit_index::]:
result = re.findall("(.*?)" + unit_list[index], amount[amount_unit_index::])
if result[0] != '': # 抽到单位前面的数字了
print(result[0], unit_list[index], end="\t")
amount_result += result[0]
else: # 没抽到单位前面的数字但是单位确实存在,默认为一,比如我告诉你百万,默认是一百万
print('一', unit_list[index], end="\t")
amount_result += '一'
amount_unit_index += (len(unit_list[index]) + 1)
continue
# 如果单位不在数字字符串中,但是数量可能存在,例如八百三,这里的三就没有单位,但是可以依据三前面的单位提取
result = re.findall(unit_list[index - 1] + "(.)", amount[amount_unit_index - 1::])
if len(result) > 0:
print(result, unit_list[index], end="\t")
amount_result += result[0]
amount_unit_index += 1
continue
# 上面两种情况都不存在 那就当前单位补零
print("零", unit_list[index], end="\t")
amount_result += "零"
# 将汉字替换为数字 四百->400
for index in range(0, len(transfer_list)):
amount_result = amount_result.replace(transfer_list[index], str(index))
return str(int(amount_result))
if __name__ == '__main__':
price_list = ["四十万零五百", "四千八百三", "零", "4331", "4百万", "4万", "百万", "百", "3万4", "3万四", "三万四", "三万4"]
result = []
for item in price_list:
result = transfer(item)
print('->', result)
print("")测试运行结果:
四 十万 零 万 [‘零’] 千 五 百 零 十 零 个 -> 400500四 十万 零 万 [‘零’] 千 五 百 零 十 零 个 -> 400500
四 千 八 百 [‘三’] 十 零 个 -> 4830
零 个 零 兆 零 千亿 零 百亿 零 十亿 零 亿 零 千万 零 百万 零 十万 零 万 零 千 零 百 零 十 零 个 -> 0
-> 4331
4 百万 零 十万 零 万 零 千 零 百 零 十 零 个 -> 4000000
4 万 零 千 零 百 零 十 零 个 -> 40000
一 百万 零 十万 零 万 零 千 零 百 零 十 零 个 -> 1000000
一 百 零 十 零 个 -> 100
3 万 [‘4’] 千 零 百 零 十 零 个 -> 34000
3 万 [‘四’] 千 零 百 零 十 零 个 -> 34000
三 万 [‘四’] 千 零 百 零 十 零 个 -> 34000
三 万 [‘4’] 千 零 百 零 十 零 个 -> 34000
Process finished with exit code 0