场景:工作中需要把数字、汉字、数字汉字混合的数转换为数字型。待转换的包括但不限于以下类型:”四十万零五百”,”四千八百三”, “零”, “4331”, “4百万”, “4万”, “百万”, “百”, “3万4”, “3万四”, “三万四”, “三万4”
我一开始用从前往后挨个转换,总是存在局限和问题。查找了网上的方法,大多数都是从后往前,挨着来,然后乘以单位之类的。
我想到个办法,可不跟网上那些妖艳的贱货一样。
我的暂时就叫补全法
其实仔细分析,相对于单位来说,待转换的都是简略写法,转换后的数字都是补全的写法,哪怕是零也会补全。比如说三万四,这个数字缺少了单位“千”,缺少了个十百位;但是数字“34000”就一个不少。可以总结为以下四种情况:
![](http://zkeeer.space/wp-content/uploads/2018/04/转数字-示意图-1024x619.png)
根据以上的情况分析,“四万零八百三”可以这样分析:
![](http://zkeeer.space/wp-content/uploads/2018/04/转数字-示意图2.png)
大体思路如上,具体的思路和伪码以及注释,见下面的代码:
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