From a4d6bfd3e487551ca3b3f7d7f34fd6892a21b58c Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 7 Oct 2023 18:30:48 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BC=98=E5=8C=96cn2an=E7=BB=93=E6=9E=84--?= =?UTF-8?q?=E6=8B=86=E5=88=86=E9=A2=84=E5=A4=84=E7=90=86=E5=92=8C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=A0=A1=E9=AA=8C=EF=BC=8C=E6=89=A9=E5=A4=A7=E9=9B=B6?= =?UTF-8?q?=E5=90=8E=E7=9C=81=E7=95=A5=E6=95=B0=E8=AF=8D=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn2an/cn2an.py | 154 ++++++++++++++++++++++++------------------------- cn2an/conf.py | 7 +++ 2 files changed, 84 insertions(+), 77 deletions(-) diff --git a/cn2an/cn2an.py b/cn2an/cn2an.py index d739a87..8600943 100644 --- a/cn2an/cn2an.py +++ b/cn2an/cn2an.py @@ -5,7 +5,7 @@ from proces import preprocess from .an2cn import An2Cn -from .conf import NUMBER_CN2AN, UNIT_CN2AN, STRICT_CN_NUMBER, NORMAL_CN_NUMBER, NUMBER_LOW_AN2CN, UNIT_LOW_AN2CN +from .conf import NUMBER_CN2AN, UNIT_CN2AN, STRICT_CN_NUMBER, NORMAL_CN_NUMBER, NUMBER_LOW_AN2CN, UNIT_LOW_AN2CN, CN_NUM_AFTER_INTERTNAL_ZERO class Cn2An(object): @@ -35,49 +35,40 @@ def cn2an(self, inputs: Union[str, int, float] = None, mode: str = "strict") -> :param mode: strict 严格,normal 正常,smart 智能 :return: 阿拉伯数字 """ - if inputs is not None or inputs == "": - if mode not in self.mode_list: - raise ValueError(f"mode 仅支持 {str(self.mode_list)} !") - - # 将数字转化为字符串 - if not isinstance(inputs, str): - inputs = str(inputs) - - # 数据预处理: - # 1. 繁体转简体 - # 2. 全角转半角 - inputs = preprocess(inputs, pipelines=[ - "traditional_to_simplified", - "full_angle_to_half_angle" - ]) - - # 特殊转化 廿 - inputs = inputs.replace("廿", "二十") - - # 检查输入数据是否有效 - sign, integer_data, decimal_data, is_all_num = self.__check_input_data_is_valid(inputs, mode) - - # smart 下的特殊情况 - if sign == 0: - return integer_data + if not inputs: + raise ValueError("输入数据为空!") + if mode not in self.mode_list: + raise ValueError(f"mode 仅支持 {str(self.mode_list)} !") + + # 将数字转化为字符串 + if not isinstance(inputs, str): + inputs = str(inputs) + + # 预处理数据 + sign, integer_data, decimal_data, mode = self.__preprecess_input_data(inputs, mode) + # smart 下的特殊情况 + if sign == 0: + return integer_data + + # 检查输入数据是否有效 + is_all_num = self.__check_input_data_is_valid(inputs, integer_data, decimal_data, mode) + + # 数据转换 + if not is_all_num: + if decimal_data is None: + output = self.__integer_convert(integer_data) else: - if not is_all_num: - if decimal_data is None: - output = self.__integer_convert(integer_data) - else: - output = self.__integer_convert(integer_data) + self.__decimal_convert(decimal_data) - # fix 1 + 0.57 = 1.5699999999999998 - output = round(output, len(decimal_data)) - else: - if decimal_data is None: - output = self.__direct_convert(integer_data) - else: - output = self.__direct_convert(integer_data) + self.__decimal_convert(decimal_data) - # fix 1 + 0.57 = 1.5699999999999998 - output = round(output, len(decimal_data)) + output = self.__integer_convert(integer_data) + self.__decimal_convert(decimal_data) + # fix 1 + 0.57 = 1.5699999999999998 + output = round(output, len(decimal_data)) else: - raise ValueError("输入数据为空!") - + if decimal_data is None: + output = self.__direct_convert(integer_data) + else: + output = self.__direct_convert(integer_data) + self.__decimal_convert(decimal_data) + # fix 1 + 0.57 = 1.5699999999999998 + output = round(output, len(decimal_data)) + return sign * output def __get_pattern(self) -> dict: @@ -124,43 +115,55 @@ def __copy_num(self, num): for n in num: cn_num += NUMBER_LOW_AN2CN[int(n)] return cn_num + + def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, str): + + # 数据预处理: + # 1. 繁体转简体 + # 2. 全角转半角 + inputs = preprocess(inputs, pipelines=[ + "traditional_to_simplified", + "full_angle_to_half_angle" + ]) + + # 特殊转化 廿 + inputs = inputs.replace("廿", "二十").replace("卅", "三十") - def __check_input_data_is_valid(self, check_data: str, mode: str) -> (int, str, str, bool): # 去除 元整、圆整、元正、圆正 stop_words = ["元整", "圆整", "元正", "圆正"] for word in stop_words: if check_data[-2:] == word: check_data = check_data[:-2] - + # 去除 元、圆 if mode != "strict": normal_stop_words = ["圆", "元"] for word in normal_stop_words: if check_data[-1] == word: check_data = check_data[:-1] - + # 处理元角分 result = self.yjf_pattern.search(check_data) if result: check_data = check_data.replace("元", "点").replace("角", "").replace("分", "") - - # 处理特殊问法:一千零十一 一万零百一十一 - if "零十" in check_data: - check_data = check_data.replace("零十", "零一十") - if "零百" in check_data: - check_data = check_data.replace("零百", "零一百") - + + # 零后省略数词时默认数词为一:一千零十一 一万零百一十一 + for cn_num in CN_NUM_AFTER_INTERTNAL_ZERO.keys(): + if cn_num in check_data: + check_data = check_data.replace(cn_num, self.cn_num_after_internal_zero[cn_num]) + for data in check_data: if data not in self.check_key_dict[mode]: raise ValueError(f"当前为{mode}模式,输入的数据不在转化范围内:{data}!") - + # 确定正负号 if check_data[0] == "负": check_data = check_data[1:] sign = -1 else: sign = 1 - + + # 按照小数点拆分并转化为中文数字 if "点" in check_data: split_data = check_data.split("点") if len(split_data) == 2: @@ -186,9 +189,22 @@ def __check_input_data_is_valid(self, check_data: str, mode: str) -> (int, str, else: output = float(integer_data) return 0, output, None, None - integer_data = re.sub(r"\d+", lambda x: self.ac.an2cn(x.group()), integer_data) mode = "normal" + + if mode == "normal": + # 口语模式:一万二,两千三,三百四,十三万六,一百二十五万三 + result_speaking_mode = self.ptn_speaking_mode.search(integer_data) + if len(integer_data) >= 3 and result_speaking_mode and result_speaking_mode.group() == integer_data: + # len(integer_data)>=3: because the minimum length of integer_data that can be matched is 3 + # to find the last unit + last_unit = result_speaking_mode.groups()[-1][-1] + _unit = UNIT_LOW_AN2CN[UNIT_CN2AN[last_unit] // 10] + integer_data = integer_data + _unit + + return sign, integer_data, decimal_data, mode + + def __check_input_data_is_valid(self, check_data: str, integer_data: str, decimal_data: str, mode: str) -> bool: result_int = self.pattern_dict[mode]["int"].search(integer_data) if result_int: @@ -197,9 +213,9 @@ def __check_input_data_is_valid(self, check_data: str, mode: str) -> (int, str, result_dec = self.pattern_dict[mode]["dec"].search(decimal_data) if result_dec: if result_dec.group() == decimal_data: - return sign, integer_data, decimal_data, False + return integer_data, decimal_data, False else: - return sign, integer_data, decimal_data, False + return integer_data, decimal_data, False else: if mode == "strict": raise ValueError(f"不符合格式的数据:{integer_data}") @@ -212,28 +228,12 @@ def __check_input_data_is_valid(self, check_data: str, mode: str) -> (int, str, result_dec = self.pattern_dict[mode]["dec"].search(decimal_data) if result_dec: if result_dec.group() == decimal_data: - return sign, integer_data, decimal_data, True + return integer_data, decimal_data, True else: - return sign, integer_data, decimal_data, True - - # 口语模式:一万二,两千三,三百四,十三万六,一百二十五万三 - result_speaking_mode = self.ptn_speaking_mode.search(integer_data) - if len(integer_data) >= 3 and result_speaking_mode and result_speaking_mode.group() == integer_data: - # len(integer_data)>=3: because the minimum length of integer_data that can be matched is 3 - # to find the last unit - last_unit = result_speaking_mode.groups()[-1][-1] - _unit = UNIT_LOW_AN2CN[UNIT_CN2AN[last_unit] // 10] - integer_data = integer_data + _unit - if decimal_data is not None: - result_dec = self.pattern_dict[mode]["dec"].search(decimal_data) - if result_dec: - if result_dec.group() == decimal_data: - return sign, integer_data, decimal_data, False - else: - return sign, integer_data, decimal_data, False - + return integer_data, decimal_data, True + raise ValueError(f"不符合格式的数据:{check_data}") - + def __integer_convert(self, integer_data: str) -> int: # 核心 output_integer = 0 diff --git a/cn2an/conf.py b/cn2an/conf.py index 547978b..42bc020 100644 --- a/cn2an/conf.py +++ b/cn2an/conf.py @@ -133,3 +133,10 @@ "万": "万", "亿": "亿", } +CN_NUM_AFTER_INTERTNAL_ZERO = { + "零十": "零一十", + "零百": "零一百", + "零千": "零一千", + "零万": "零一万", + "零亿": "零一亿", +} \ No newline at end of file From 66e3ed54c99433b24ff50563919942c243b28619 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 7 Oct 2023 18:59:12 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E6=94=AF=E6=8C=81k=E3=80=81w=E7=AD=89?= =?UTF-8?q?=E5=8D=95=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn2an/cn2an.py | 29 ++++++++++++++++------------- cn2an/conf.py | 7 +++++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cn2an/cn2an.py b/cn2an/cn2an.py index 8600943..e7583b9 100644 --- a/cn2an/cn2an.py +++ b/cn2an/cn2an.py @@ -5,7 +5,7 @@ from proces import preprocess from .an2cn import An2Cn -from .conf import NUMBER_CN2AN, UNIT_CN2AN, STRICT_CN_NUMBER, NORMAL_CN_NUMBER, NUMBER_LOW_AN2CN, UNIT_LOW_AN2CN, CN_NUM_AFTER_INTERTNAL_ZERO +from .conf import NUMBER_CN2AN, UNIT_CN2AN, UNIT_EN2AN, STRICT_CN_NUMBER, NORMAL_CN_NUMBER, NUMBER_LOW_AN2CN, UNIT_LOW_AN2CN, CN_NUM_AFTER_INTERTNAL_ZERO class Cn2An(object): @@ -91,12 +91,12 @@ def __get_pattern(self) -> dict: str_dec_pattern = "^[零一二三四五六七八九]{0,15}[一二三四五六七八九]$" nor_dec_pattern = "^[零一二三四五六七八九]{0,16}$" - for str_num in self.strict_cn_number.keys(): - str_int_pattern = str_int_pattern.replace(str_num, self.strict_cn_number[str_num]) - str_dec_pattern = str_dec_pattern.replace(str_num, self.strict_cn_number[str_num]) - for nor_num in self.normal_cn_number.keys(): - nor_int_pattern = nor_int_pattern.replace(nor_num, self.normal_cn_number[nor_num]) - nor_dec_pattern = nor_dec_pattern.replace(nor_num, self.normal_cn_number[nor_num]) + for str_num, str_cn_num in self.strict_cn_number.items(): + str_int_pattern = str_int_pattern.replace(str_num, str_cn_num) + str_dec_pattern = str_dec_pattern.replace(str_num, str_cn_num) + for nor_num, nor_cn_num in self.normal_cn_number.items(): + nor_int_pattern = nor_int_pattern.replace(nor_num, nor_cn_num) + nor_dec_pattern = nor_dec_pattern.replace(nor_num, nor_cn_num) pattern_dict = { "strict": { @@ -121,14 +121,18 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, # 数据预处理: # 1. 繁体转简体 # 2. 全角转半角 - inputs = preprocess(inputs, pipelines=[ + check_data = preprocess(check_data, pipelines=[ "traditional_to_simplified", "full_angle_to_half_angle" ]) # 特殊转化 廿 - inputs = inputs.replace("廿", "二十").replace("卅", "三十") + check_data = check_data.replace("廿", "二十").replace("卅", "三十") + # 支持k、w等单位 + for en_unit, cn_unit in UNIT_EN2AN.items(): + check_data.replace(en_unit, cn_unit) + # 去除 元整、圆整、元正、圆正 stop_words = ["元整", "圆整", "元正", "圆正"] for word in stop_words: @@ -148,9 +152,8 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, check_data = check_data.replace("元", "点").replace("角", "").replace("分", "") # 零后省略数词时默认数词为一:一千零十一 一万零百一十一 - for cn_num in CN_NUM_AFTER_INTERTNAL_ZERO.keys(): - if cn_num in check_data: - check_data = check_data.replace(cn_num, self.cn_num_after_internal_zero[cn_num]) + for cn_num, new_cn_num in CN_NUM_AFTER_INTERTNAL_ZERO.items(): + check_data = check_data.replace(cn_num, new_cn_num) for data in check_data: if data not in self.check_key_dict[mode]: @@ -184,7 +187,7 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, result1 = self.pattern1.search(integer_data) if result1: if result1.group() == integer_data: - if integer_data[-1] in UNIT_CN2AN.keys(): + if integer_data[-1] in UNIT_CN2AN: output = int(float(integer_data[:-1]) * UNIT_CN2AN[integer_data[-1]]) else: output = float(integer_data) diff --git a/cn2an/conf.py b/cn2an/conf.py index 42bc020..df8d759 100644 --- a/cn2an/conf.py +++ b/cn2an/conf.py @@ -22,6 +22,13 @@ "九": 9, "玖": 9, } +UNIT_EN2AN = { + "q": "千", + "k": "千", + "w": "万", + "e": "亿", + "y": "亿", +} UNIT_CN2AN = { "十": 10, "拾": 10, From 6900315fb088af563cd29e8f599e864e4442b590 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 8 Oct 2023 00:36:17 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=8D=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E7=9A=84=E4=B8=AD=E6=96=87=E6=95=B0=E5=AD=97=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn2an/cn2an.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cn2an/cn2an.py b/cn2an/cn2an.py index e7583b9..0dbe45b 100644 --- a/cn2an/cn2an.py +++ b/cn2an/cn2an.py @@ -72,18 +72,19 @@ def cn2an(self, inputs: Union[str, int, float] = None, mode: str = "strict") -> return sign * output def __get_pattern(self) -> dict: + # 整数严格检查 _0 = "[零]" _1_9 = "[一二三四五六七八九]" - _10_99 = f"{_1_9}?[十]{_1_9}?" + _10_99 = f"{_1_9}?[十][零]?{_1_9}?" _1_99 = f"({_10_99}|{_1_9})" - _100_999 = f"({_1_9}[百]([零]{_1_9})?|{_1_9}[百]{_10_99})" + _100_999 = f"({_1_9}[百]([零]{_1_9})?|{_1_9}[百][零]?{_10_99})" _1_999 = f"({_100_999}|{_1_99})" - _1000_9999 = f"({_1_9}[千]([零]{_1_99})?|{_1_9}[千]{_100_999})" + _1000_9999 = f"({_1_9}[千]([零]{_1_9})?|{_1_9}[千]([零]?{_10_99})?|{_1_9}[千][零]?{_100_999})" _1_9999 = f"({_1000_9999}|{_1_999})" - _10000_99999999 = f"({_1_9999}[万]([零]{_1_999})?|{_1_9999}[万]{_1000_9999})" + _10000_99999999 = f"({_1_9999}[万]([零]{_1_9})?|{_1_9999}[万]([零]?({_10_99}|{_100_999}))?|{_1_9999}[万][零]?{_1000_9999})" _1_99999999 = f"({_10000_99999999}|{_1_9999})" - _100000000_9999999999999999 = f"({_1_99999999}[亿]([零]{_1_99999999})?|{_1_99999999}[亿]{_10000_99999999})" + _100000000_9999999999999999 = f"({_1_99999999}[亿]([零]{_1_9})?|{_1_99999999}[亿]([零]?({_10_99}|{_100_999}|{_1000_9999}|{_10000_99999999}))?|{_1_99999999}[亿][零]?{_10000_99999999})" _1_9999999999999999 = f"({_100000000_9999999999999999}|{_1_99999999})" str_int_pattern = f"^({_0}|{_1_9999999999999999})$" nor_int_pattern = f"^({_0}|{_1_9999999999999999})$" @@ -131,7 +132,7 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, # 支持k、w等单位 for en_unit, cn_unit in UNIT_EN2AN.items(): - check_data.replace(en_unit, cn_unit) + check_data = check_data.replace(en_unit, cn_unit) # 去除 元整、圆整、元正、圆正 stop_words = ["元整", "圆整", "元正", "圆正"] @@ -216,9 +217,9 @@ def __check_input_data_is_valid(self, check_data: str, integer_data: str, decima result_dec = self.pattern_dict[mode]["dec"].search(decimal_data) if result_dec: if result_dec.group() == decimal_data: - return integer_data, decimal_data, False + return False else: - return integer_data, decimal_data, False + return False else: if mode == "strict": raise ValueError(f"不符合格式的数据:{integer_data}") @@ -231,9 +232,9 @@ def __check_input_data_is_valid(self, check_data: str, integer_data: str, decima result_dec = self.pattern_dict[mode]["dec"].search(decimal_data) if result_dec: if result_dec.group() == decimal_data: - return integer_data, decimal_data, True + return True else: - return integer_data, decimal_data, True + return True raise ValueError(f"不符合格式的数据:{check_data}") From ae344b3fb7ed2b8fd6459d5d7b7221f5b6ec05e5 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 8 Oct 2023 00:50:35 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=94=AF=E6=8C=81k=E3=80=81w=E7=AD=89?= =?UTF-8?q?=E5=8D=95=E4=BD=8D=20+=20=E6=94=AF=E6=8C=81=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn2an/conf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cn2an/conf.py b/cn2an/conf.py index df8d759..e5d576b 100644 --- a/cn2an/conf.py +++ b/cn2an/conf.py @@ -24,10 +24,15 @@ } UNIT_EN2AN = { "q": "千", + "Q": "千", "k": "千", + "K": "千", "w": "万", + "W": "万", "e": "亿", + "E": "亿", "y": "亿", + "Y": "亿", } UNIT_CN2AN = { "十": 10, From 73a793e2900dcbdc8fdbb345921d7847b23abd19 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 8 Oct 2023 02:09:50 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8D=83=E5=88=86?= =?UTF-8?q?=E7=AC=A6=E5=8F=B7=EF=BC=8C=E6=94=AF=E6=8C=81=E4=BA=BF=E7=9A=84?= =?UTF-8?q?=E7=89=B9=E6=AE=8A=E8=AF=B4=E6=B3=95=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=B0=8F=E6=95=B0=E7=82=B9=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn2an/cn2an.py | 73 +++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/cn2an/cn2an.py b/cn2an/cn2an.py index 0dbe45b..b316721 100644 --- a/cn2an/cn2an.py +++ b/cn2an/cn2an.py @@ -126,13 +126,6 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, "traditional_to_simplified", "full_angle_to_half_angle" ]) - - # 特殊转化 廿 - check_data = check_data.replace("廿", "二十").replace("卅", "三十") - - # 支持k、w等单位 - for en_unit, cn_unit in UNIT_EN2AN.items(): - check_data = check_data.replace(en_unit, cn_unit) # 去除 元整、圆整、元正、圆正 stop_words = ["元整", "圆整", "元正", "圆正"] @@ -147,15 +140,29 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, if check_data[-1] == word: check_data = check_data[:-1] - # 处理元角分 - result = self.yjf_pattern.search(check_data) - if result: - check_data = check_data.replace("元", "点").replace("角", "").replace("分", "") + # 特殊转化 廿 + check_data = check_data.replace("廿", "二十").replace("卅", "三十") + + # 支持k、w等单位 + for en_unit, cn_unit in UNIT_EN2AN.items(): + check_data = check_data.replace(en_unit, cn_unit) + + # 去除千分符 + check_data = check_data.replace(",", "") + + # 亿的特殊说法 + check_data = check_data.replace("个亿", "亿") # 零后省略数词时默认数词为一:一千零十一 一万零百一十一 for cn_num, new_cn_num in CN_NUM_AFTER_INTERTNAL_ZERO.items(): check_data = check_data.replace(cn_num, new_cn_num) + # 处理元角分 + result = self.yjf_pattern.search(check_data) + if result: + check_data = check_data.replace("元", "点").replace("角", "").replace("分", "") + + # 处理完成校验 for data in check_data: if data not in self.check_key_dict[mode]: raise ValueError(f"当前为{mode}模式,输入的数据不在转化范围内:{data}!") @@ -167,34 +174,34 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, else: sign = 1 - # 按照小数点拆分并转化为中文数字 - if "点" in check_data: - split_data = check_data.split("点") - if len(split_data) == 2: - integer_data, decimal_data = split_data - # 将 smart 模式中的阿拉伯数字转化成中文数字 - if mode == "smart": - integer_data = re.sub(r"\d+", lambda x: self.ac.an2cn(x.group()), integer_data) - decimal_data = re.sub(r"\d+", lambda x: self.__copy_num(x.group()), decimal_data) - mode = "normal" - else: - raise ValueError("数据中包含不止一个点!") - else: + # 将 smart 模式中的阿拉伯数字转化成中文数字 + if "点" not in check_data and mode == "smart": + # 10.1万 = 10.1 * 10000 + result1 = self.pattern1.search(check_data) + if result1 and result1.group() == check_data: + if check_data[-1] in UNIT_CN2AN: + output = int(float(check_data[:-1]) * UNIT_CN2AN[check_data[-1]]) + else: + output = float(check_data) + return 0, output, None, None + + # 拆分整数和小数 + split_data = check_data.replace(".", "点").split("点") + if len(split_data) == 1: integer_data = check_data decimal_data = None + if mode == "smart": + integer_data = re.sub(r"\d+", lambda x: self.ac.an2cn(x.group()), integer_data) + mode = "normal" + elif len(split_data) == 2: + integer_data, decimal_data = split_data # 将 smart 模式中的阿拉伯数字转化成中文数字 if mode == "smart": - # 10.1万 10.1 - result1 = self.pattern1.search(integer_data) - if result1: - if result1.group() == integer_data: - if integer_data[-1] in UNIT_CN2AN: - output = int(float(integer_data[:-1]) * UNIT_CN2AN[integer_data[-1]]) - else: - output = float(integer_data) - return 0, output, None, None integer_data = re.sub(r"\d+", lambda x: self.ac.an2cn(x.group()), integer_data) + decimal_data = re.sub(r"\d+", lambda x: self.__copy_num(x.group()), decimal_data) mode = "normal" + else: + raise ValueError("数据中包含不止一个点!") if mode == "normal": # 口语模式:一万二,两千三,三百四,十三万六,一百二十五万三 From 1b28c04c3a9a1ab0aec4c479ffe36c65a87385f1 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 11 Oct 2023 16:47:34 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=98=BF=E6=8B=89?= =?UTF-8?q?=E4=BC=AF=E6=95=B0=E5=AD=97+=E4=B8=AD=E6=96=87=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E7=9A=84=E8=AF=86=E5=88=AB=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?1.5=E5=8D=83=E4=B8=87=E8=BF=99=E7=A7=8D=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E5=8D=95=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn2an/cn2an.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cn2an/cn2an.py b/cn2an/cn2an.py index b316721..07dc105 100644 --- a/cn2an/cn2an.py +++ b/cn2an/cn2an.py @@ -3,6 +3,7 @@ from typing import Union from proces import preprocess +from functools import reduce from .an2cn import An2Cn from .conf import NUMBER_CN2AN, UNIT_CN2AN, UNIT_EN2AN, STRICT_CN_NUMBER, NORMAL_CN_NUMBER, NUMBER_LOW_AN2CN, UNIT_LOW_AN2CN, CN_NUM_AFTER_INTERTNAL_ZERO @@ -23,7 +24,7 @@ def __init__(self) -> None: self.ac = An2Cn() self.mode_list = ["strict", "normal", "smart"] self.yjf_pattern = re.compile(fr"^.*?[元圆][{self.all_num}]角([{self.all_num}]分)?$") - self.pattern1 = re.compile(fr"^-?\d+(\.\d+)?[{self.all_unit}]?$") + self.an_cu_pattern = re.compile(fr"^-?\d+(\.\d+)?([{self.all_unit}]*)$") self.ptn_all_num = re.compile(f"^[{self.all_num}]+$") # "十?" is for special case "十一万三" self.ptn_speaking_mode = re.compile(f"^([{self.all_num}]{{0,2}}[{self.all_unit}])+[{self.all_num}]$") @@ -176,14 +177,11 @@ def __preprecess_input_data(self, check_data: str, mode: str) -> (int, str, str, # 将 smart 模式中的阿拉伯数字转化成中文数字 if "点" not in check_data and mode == "smart": - # 10.1万 = 10.1 * 10000 - result1 = self.pattern1.search(check_data) - if result1 and result1.group() == check_data: - if check_data[-1] in UNIT_CN2AN: - output = int(float(check_data[:-1]) * UNIT_CN2AN[check_data[-1]]) - else: - output = float(check_data) - return 0, output, None, None + # 阿拉伯数字+中文单位:10.1千万 = 10.1 * 1000 * 10000 + matcher = self.an_cu_pattern.search(check_data) + if matcher and matcher.group() == check_data: + unit = reduce(lambda x,y:x*y, [UNIT_CN2AN[unit_data] for unit_data in matcher.group(2)]) if matcher.group(2) else 1 + return 0, float(check_data.replace(matcher.group(2), '')) * unit, None, None # 拆分整数和小数 split_data = check_data.replace(".", "点").split("点")