chinese2digits/
lib.rs

1// #[warn(unused_assignments)]
2// #[macro_use] extern crate lazy_static;
3// extern crate regex;
4use regex::Regex;
5//pcre2 速度快
6// extern crate pcre2;
7// use pcre2::bytes::Regex;
8use std::collections::HashMap;
9use std::str;
10use rust_decimal::prelude::*;
11
12// 中文转阿拉伯数字
13static CHINESE_CHAR_NUMBER_LIST: [(&str, i32); 29] = [
14	("幺", 1),
15	("零", 0),
16	("一", 1),
17	("二", 2),
18	("两", 2),
19	("三", 3),
20	("四", 4),
21	("五", 5),
22	("六", 6),
23	("七", 7),
24	("八", 8),
25	("九", 9),
26	("十", 10),
27	("百", 100),
28	("千", 1000),
29	("万", 10000),
30	("亿", 100000000),
31	("壹", 1),
32	("贰", 2),
33	("叁", 3),
34	("肆", 4),
35	("伍", 5),
36	("陆", 6),
37	("柒", 7),
38	("捌", 8),
39	("玖", 9),
40	("拾", 10),
41	("佰", 100),
42	("仟", 1000),
43];
44
45static CHINESE_PURE_COUNTING_UNIT_LIST: [&str; 5] = ["十", "百", "千", "万", "亿"];
46
47static CHINESE_PURE_NUMBER_LIST: [&str; 13] = [
48	"幺", "一", "二", "两", "三", "四", "五", "六", "七", "八", "九", "十", "零",
49];
50
51// CoreCHToDigits 是核心转化函数
52fn core_ch_to_digits(chinese_chars_to_trans: String) -> String {
53	let chinese_chars = chinese_chars_to_trans;
54	let total: String;
55	let mut temp_val = "".to_string(); //#用以记录临时是否建议数字拼接的字符串 例如 三零万 的三零
56	let mut counting_unit: i32 = 1; //#表示单位:个十百千,用以计算单位相乘 例如八百万 百万是相乘的方法,但是如果万前面有 了一千八百万 这种,千和百不能相乘,要相加...
57	let mut counting_unit_from_string: Vec<i32> = vec![1]; //#原始字符串提取的单位应该是一个list  在计算的时候,新的单位应该是本次取得的数字乘以已经发现的最大单位,例如 4千三百五十万, 等于 4000万+300万+50万
58	let mut temp_val_int: i32;
59	let chinese_char_number_dict: HashMap<&str, i32> =
60		CHINESE_CHAR_NUMBER_LIST.into_iter().collect();
61
62	let mut temp_total: i32 = 0;
63	// // counting_unit := 1
64	// 表示单位:个十百千...
65	for i in (0..chinese_chars.chars().count()).rev() {
66		// println!("{}",i);
67		let char_to_get = chinese_chars.chars().nth(i).unwrap().to_string();
68		let val_from_hash_map = chinese_char_number_dict.get(char_to_get.as_str());
69
70		match val_from_hash_map {
71			Some(val_from_hash_map) => {
72				let val = *val_from_hash_map;
73				if val >= 10 && i == 0_usize {
74					// 应对 十三 十四 十*之类
75					if val > counting_unit {
76						counting_unit = val;
77						temp_total = temp_total + val;
78						counting_unit_from_string.push(val);
79					} else {
80						counting_unit_from_string.push(val);
81						let max_value_option = counting_unit_from_string.iter().max();
82						let max_value = max_value_option.unwrap();
83						counting_unit = max_value * val;
84					}
85				} else if val >= 10 {
86					if val > counting_unit {
87						counting_unit = val;
88						counting_unit_from_string.push(val);
89					} else {
90						counting_unit_from_string.push(val);
91						// let max_value = counting_unit_from_string.iter().max();
92						let max_value_option = counting_unit_from_string.iter().max();
93						let max_value = max_value_option.unwrap();
94						counting_unit = max_value * val;
95					}
96				} else {
97					if i > 0 {
98						// #如果下一个不是单位 则本次也是拼接
99						let pre_val_temp_option = chinese_char_number_dict.get(
100							chinese_chars
101								.chars()
102								.nth(i - 1)
103								.unwrap()
104								.to_string()
105								.as_str(),
106						);
107						match pre_val_temp_option {
108							Some(pre_val_temp_option) => {
109								let pre_val_temp = *pre_val_temp_option;
110								if pre_val_temp < 10 {
111									// temp_val = strconv.Itoa(val) + temp_val;
112									temp_val = val.to_string() + &temp_val;
113								} else {
114									// #说明已经有大于10的单位插入 要数学计算了
115									// #先拼接再计算
116									// #如果取值不大于10 说明是0-9 则继续取值 直到取到最近一个大于10 的单位   应对这种30万20千 这样子
117									temp_val_int =
118										(val.to_string() + &temp_val).parse::<i32>().unwrap();
119									temp_total = temp_total + counting_unit * temp_val_int;
120									// #计算后 把临时字符串置位空
121									temp_val = "".to_string();
122								}
123							}
124							None => {}
125						}
126					} else {
127						// #那就是无论如何要收尾了
128						//如果counting unit 等于1  说明所有字符串都是直接拼接的,不用计算,不然会丢失前半部分的零
129						if counting_unit == 1 {
130							temp_val = val.to_string() + &temp_val;
131						} else {
132							temp_val_int = (val.to_string() + &temp_val).parse::<i32>().unwrap();
133							temp_total = temp_total + counting_unit * temp_val_int;
134						}
135					}
136				}
137			}
138			None => println!("No string in number"),
139		}
140	}
141	//如果 total 为0  但是 counting_unit 不为0  说明结果是 十万这种  最终直接取结果 十万
142	if temp_total == 0 {
143		if counting_unit > 10 {
144			// 转化为字符串
145			total = counting_unit.to_string();
146		} else {
147			//counting Unit 为1  且tempval 不为空 说明是没有单位的纯数字拼接
148			if temp_val != "" {
149				total = temp_val;
150			} else {
151				// 转化为字符串
152				total = temp_total.to_string();
153			}
154		}
155	} else {
156		// 转化为字符串
157		total = temp_total.to_string();
158	}
159
160	return total;
161}
162
163//汉字切分是否正确  分之 切分
164fn check_number_seg(chinese_number_list: &Vec<String>, origin_text: &String) -> Vec<String> {
165	let mut new_chinese_number_list: Vec<String> = [].to_vec();
166	// #用来控制是否前一个已经合并过  防止多重合并
167	let mut temp_pre_text: String = "".to_string();
168	let mut temp_mixed_string: String;
169	let seg_len = chinese_number_list.len();
170	if seg_len > 0 {
171		// #加入唯一的一个 或者第一个
172		if chinese_number_list[0].starts_with("分之") {
173			// #如果以分之开头 记录本次 防止后面要用 是否出现连续的 分之
174			new_chinese_number_list.push(
175				(&chinese_number_list[0][2..(chinese_number_list[0].chars().count())]).to_string(),
176			);
177		} else {
178			new_chinese_number_list.push(chinese_number_list.get(0).unwrap().to_string())
179		}
180
181		if seg_len > 1 {
182			for i in 1..seg_len {
183				// #判断本字符是不是以  分之  开头
184				if (chinese_number_list[i]).starts_with("分之") {
185					// #如果是以 分之 开头 那么检查他和他见面的汉子数字是不是连续的 即 是否在原始字符串出现
186					temp_mixed_string = chinese_number_list.get(i - 1).unwrap().to_string()
187						+ &chinese_number_list[i];
188
189					if origin_text.contains(&temp_mixed_string.to_string()) {
190						// #如果连续的上一个字段是以分之开头的  本字段又以分之开头
191						if temp_pre_text != "" {
192							// #检查上一个字段的末尾是不是 以 百 十 万 的单位结尾
193							if CHINESE_PURE_COUNTING_UNIT_LIST
194								.iter()
195								.any(|&x| x == (&temp_pre_text.chars().last().unwrap().to_string()))
196							{
197								//上一个字段最后一个数据
198								let temp_last_chinese_number =
199									new_chinese_number_list.last().unwrap().to_string();
200								// #先把上一个记录进去的最后一位去掉
201								let temp_new_chinese_number_list_len =
202									new_chinese_number_list.len();
203								let temp_last_chinese_number_char_list: Vec<char> =
204									temp_last_chinese_number.chars().collect();
205								//把暂存结果的上一个 最后一个单位去掉
206								new_chinese_number_list[temp_new_chinese_number_list_len - 1] =
207									temp_last_chinese_number_char_list
208										[0..(temp_last_chinese_number_char_list.len() - 1)]
209										.iter()
210										.collect();
211								// #如果结果是确定的,那么本次的字段应当加上上一个字段的最后一个字
212								new_chinese_number_list.push(
213									temp_pre_text
214										.chars()
215										.nth(temp_pre_text.chars().count() - 1)
216										.unwrap()
217										.to_string() + &chinese_number_list[i],
218								);
219							} else {
220								// #如果上一个字段不是以单位结尾  同时他又是以分之开头,那么 本次把分之去掉
221								new_chinese_number_list
222									.push((&chinese_number_list[i][2..]).to_string())
223							}
224						} else {
225							// #上一个字段不以分之开头,那么把两个字段合并记录
226							if new_chinese_number_list.len() > 0 {
227								//把最后一位赋值
228								// newChineseNumberList[len(newChineseNumberList)-1] = tempMixedString
229								let temp_new_chinese_number_list_len =
230									new_chinese_number_list.len();
231								new_chinese_number_list[temp_new_chinese_number_list_len - 1] =
232									temp_mixed_string;
233							} else {
234								new_chinese_number_list.push(temp_mixed_string);
235							}
236						}
237					} else {
238						// #说明前一个数字 和本数字不是连续的
239						// #本数字去掉分之二字
240						new_chinese_number_list.push((&chinese_number_list[i][2..]).to_string())
241					}
242					// #记录以 分之 开头的字段  用以下一个汉字字段判别
243					temp_pre_text = chinese_number_list.get(i).unwrap().to_string();
244				} else {
245					// #不是  分之 开头 那么把本数字加入序列
246					new_chinese_number_list.push(chinese_number_list.get(i).unwrap().to_string());
247					// #记录把不是 分之 开头的字段  临时变量记为空
248					temp_pre_text = "".to_string();
249				}
250			}
251		}
252	}
253	return new_chinese_number_list;
254}
255
256fn check_chinese_number_reasonable(ch_number: &String) -> bool {
257	if ch_number.chars().count() > 0 {
258		// #由于在上个检查点 已经把阿拉伯数字转为中文 因此不用检查阿拉伯数字部分
259		// """
260		// 如果汉字长度大于0 则判断是不是 万  千  单字这种
261		// """
262		for i in CHINESE_PURE_NUMBER_LIST {
263			if ch_number.contains(&i.to_string()) {
264				return true;
265			}
266		}
267	}
268	return false;
269}
270
271// """
272// 阿拉伯数字转中文
273// """
274static DIGITS_CHAR_CHINESE_DICT_KEY: [&str; 14] = [
275	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "%", "‰", "‱", ".",
276];
277static DIGITS_CHAR_CHINESE_DICT: [(&str, &str); 14] = [
278	("0", "零"),
279	("1", "一"),
280	("2", "二"),
281	("3", "三"),
282	("4", "四"),
283	("5", "五"),
284	("6", "六"),
285	("7", "七"),
286	("8", "八"),
287	("9", "九"),
288	("%", "百分之"),
289	("‰", "千分之"),
290	("‱", "万分之"),
291	(".", "点"),
292];
293
294static CHINESE_PER_COUNTING_STRING_LIST: [&str; 3] = ["百分之", "千分之", "万分之"];
295
296static TRADITIONAL_CONVERT_DICT_STATIC: [(&str, &str); 9] = [
297	("壹", "一"),
298	("贰", "二"),
299	("叁", "三"),
300	("肆", "四"),
301	("伍", "五"),
302	("陆", "六"),
303	("柒", "七"),
304	("捌", "八"),
305	("玖", "九"),
306];
307static SPECIAL_TRADITIONAL_COUNTING_UNIT_CHAR_DICT_STATIC: [(&str, &str); 5] = [
308	("拾", "十"),
309	("佰", "百"),
310	("仟", "千"),
311	("萬", "万"),
312	("億", "亿"),
313];
314static SPECIAL_NUMBER_CHAR_DICT: [(&str, &str); 2] = [("两", "二"), ("俩", "二")];
315// static CHINESE_PURE_NUMBER_LIST: [&str; 13] = ["幺", "一", "二", "两", "三", "四", "五", "六", "七", "八", "九", "十", "零"];
316static CHINESE_SIGN_LIST: [&str; 4] = ["正", "负", "+", "-"];
317
318//阿拉伯数字转中文
319fn digits_to_ch_chars(mixed_string_list: &Vec<String>) -> Vec<String> {
320	let mut result_list: Vec<String> = vec![];
321	let digits_char_chinese_dict: HashMap<&str, &str> =
322		DIGITS_CHAR_CHINESE_DICT.into_iter().collect();
323	// for i := 0; i < len(mixedStringList); i++ {
324	for i in mixed_string_list.iter() {
325		let mut mixed_string = i.to_string();
326		if mixed_string.starts_with(".") {
327			mixed_string = "0".to_string() + &mixed_string;
328		}
329		for key in DIGITS_CHAR_CHINESE_DICT_KEY.iter() {
330			if mixed_string.contains(&key.to_string()) {
331				mixed_string = mixed_string.replace(
332					key,
333					digits_char_chinese_dict
334						.get(key)
335						.unwrap()
336						.to_string()
337						.as_str(),
338				);
339				// #应当是只要有百分号 就挪到前面 阿拉伯数字没有四百分之的说法
340				// #防止这种 3%万 这种问题
341				for kk in CHINESE_PER_COUNTING_STRING_LIST.iter() {
342					if mixed_string.contains(&kk.to_string()) {
343						mixed_string = kk.to_string() + &mixed_string.replace(kk, "");
344					}
345				}
346			}
347		}
348		result_list.push(mixed_string);
349	}
350
351	return result_list;
352}
353
354// """
355// 繁体简体转换 及  单位  特殊字符转换 两千变二千
356// """
357fn traditional_text_convert_func(ch_string: &String, simplif_convert_switch: bool) -> String {
358	// chStringList := []rune(chString)
359	let mut ch_string_list: Vec<char> = ch_string.chars().collect();
360
361	let string_length = ch_string.chars().count();
362	let mut char_to_get: String;
363	let traditional_convert_dict: HashMap<&str, &str> =
364		TRADITIONAL_CONVERT_DICT_STATIC.into_iter().collect();
365	let special_traditional_counting_unit_char_dict: HashMap<&str, &str> =
366		SPECIAL_TRADITIONAL_COUNTING_UNIT_CHAR_DICT_STATIC
367			.into_iter()
368			.collect();
369	let special_number_char_dict: HashMap<&str, &str> =
370		SPECIAL_NUMBER_CHAR_DICT.into_iter().collect();
371	if simplif_convert_switch {
372		for i in 0..ch_string_list.len() {
373			// #繁体中文数字转简体中文数字
374			// charToGet = string(chStringList[i])
375			char_to_get = ch_string_list[i].to_string();
376			let value = traditional_convert_dict.get(char_to_get.as_str());
377			match value {
378				Some(value) => {
379					ch_string_list[i] = (*value).chars().nth(0).unwrap();
380				}
381				None => {}
382			}
383		}
384	}
385	if string_length > 1 {
386		// #检查繁体单体转换
387		for i in 0..string_length {
388			// #如果 前后有 pure 汉字数字 则转换单位为简体
389			char_to_get = ch_string_list[i].to_string();
390			// value, exists := SPECIAL_TRADITIONAl_COUNTING_UNIT_CHAR_DICT[charToGet]
391			let value = special_traditional_counting_unit_char_dict.get(char_to_get.as_str());
392			// # 如果前后有单纯的数字 则进行单位转换
393			match value {
394				Some(value) => {
395					if i == 0 {
396						if CHINESE_PURE_NUMBER_LIST
397							.iter()
398							.any(|&x| x == ch_string_list[i + 1].to_string())
399						{
400							ch_string_list[i] = (*value).chars().nth(0).unwrap();
401						}
402					} else if i == (string_length - 1) {
403						if CHINESE_PURE_NUMBER_LIST
404							.iter()
405							.any(|&x| x == ch_string_list[i - 1].to_string())
406						{
407							ch_string_list[i] = (*value).chars().nth(0).unwrap();
408						}
409					} else {
410						if (CHINESE_PURE_NUMBER_LIST
411							.iter()
412							.any(|&x| x == ch_string_list[i - 1].to_string()))
413							|| (CHINESE_PURE_NUMBER_LIST
414								.iter()
415								.any(|&x| x == ch_string_list[i + 1].to_string()))
416						{
417							ch_string_list[i] = (*value).chars().nth(0).unwrap();
418						}
419					}
420				}
421				None => {}
422			}
423			// #特殊变换 俩变二
424			char_to_get = ch_string_list[i].to_string();
425			let value = special_number_char_dict.get(char_to_get.as_str());
426			// # 如果前后有单纯的数字 则进行单位转换
427			match value {
428				Some(value) => {
429					if i == 0 {
430						if CHINESE_PURE_COUNTING_UNIT_LIST
431							.iter()
432							.any(|&x| x == ch_string_list[i + 1].to_string())
433						{
434							ch_string_list[i] = (*value).chars().nth(0).unwrap();
435						}
436					} else if i == (string_length - 1) {
437						if CHINESE_PURE_COUNTING_UNIT_LIST
438							.iter()
439							.any(|&x| x == ch_string_list[i - 1].to_string())
440						{
441							ch_string_list[i] = (*value).chars().nth(0).unwrap();
442						}
443					} else {
444						if (CHINESE_PURE_COUNTING_UNIT_LIST
445							.iter()
446							.any(|&x| x == ch_string_list[i - 1].to_string()))
447							|| (CHINESE_PURE_COUNTING_UNIT_LIST
448								.iter()
449								.any(|&x| x == ch_string_list[i + 1].to_string()))
450						{
451							ch_string_list[i] = (*value).chars().nth(0).unwrap();
452						}
453					}
454				}
455				None => {}
456			}
457		}
458	}
459	let final_ch_string_list: String = ch_string_list.iter().collect();
460
461	return final_ch_string_list;
462}
463
464// """
465// 标准表述转换  三千二 变成 三千零二  三千十二变成 三千零一十二
466// """
467fn standard_ch_number_convert(ch_number_string: String) -> String {
468	let ch_number_string_list: Vec<char> = ch_number_string.chars().collect();
469
470	let mut new_ch_number_string_list: String = ch_number_string;
471
472	// #大于2的长度字符串才有检测和补位的必要
473	if ch_number_string_list.len() > 2 {
474		// #十位补一:
475		let ten_number_index = ch_number_string_list
476			.iter()
477			.position(|&x| x == "十".chars().nth(0).unwrap());
478		match ten_number_index {
479			Some(ten_number_index) => {
480				if ten_number_index == 0_usize {
481					new_ch_number_string_list = "一".to_string() + &new_ch_number_string_list;
482				} else {
483					// # 如果没有左边计数数字 插入1
484					if !(CHINESE_PURE_NUMBER_LIST.iter().any(|&x| {
485						x == ch_number_string_list[(ten_number_index - 1)]
486							.to_string()
487							.as_str()
488					})) {
489						let temp_left_part: String =
490							ch_number_string_list[0..ten_number_index].iter().collect();
491						let temp_right_part: String =
492							ch_number_string_list[ten_number_index..].iter().collect();
493						new_ch_number_string_list = temp_left_part + "一" + &temp_right_part;
494					}
495				}
496			}
497			None => {}
498		}
499
500		// #差位补零
501		// #逻辑 如果最后一个单位 不是十结尾 而是百以上 则数字后面补一个比最后一个出现的单位小一级的单位
502		// #从倒数第二位开始看,且必须是倒数第二位就是单位的才符合条件
503
504		let temp_new_ch_number_string_list: Vec<char> = new_ch_number_string_list.chars().collect();
505
506		let last_counting_unit = CHINESE_PURE_COUNTING_UNIT_LIST.iter().position(|&x| {
507			x == temp_new_ch_number_string_list[temp_new_ch_number_string_list.len() - 2]
508				.to_string()
509				.as_str()
510		});
511		// # 如果最末位的是百开头
512		match last_counting_unit {
513			Some(last_counting_unit) => {
514				if last_counting_unit >= 1_usize {
515					// # 则字符串最后拼接一个比最后一个单位小一位的单位 例如四万三 变成四万三千
516					// # 如果最后一位结束的是亿 则补千万
517					if last_counting_unit == 4_usize {
518						new_ch_number_string_list = new_ch_number_string_list + &"千万".to_string();
519					} else {
520						new_ch_number_string_list = new_ch_number_string_list
521							+ &CHINESE_PURE_COUNTING_UNIT_LIST[last_counting_unit - 1].to_string();
522					}
523				}
524			}
525			None => {}
526		}
527	}
528	//大于一的检查是不是万三,千四五这种
529	let mut per_count_switch = false;
530	let temp_new_ch_number_string_list: Vec<char> = new_ch_number_string_list.chars().collect();
531	if temp_new_ch_number_string_list.len() > 1 {
532		// #十位补一:
533		// fistCharCheckResult := isExistItem(string(tempNewChNumberStringList[0]), []string{"千", "万", "百"})
534
535		let _first_char_check_result = ["千", "万", "百"]
536			.iter()
537			.position(|&x| x == temp_new_ch_number_string_list[0].to_string().as_str());
538		match _first_char_check_result {
539			Some(_first_char_check_result) => {
540				for i in 1..temp_new_ch_number_string_list.len() {
541					// #其余位数都是纯数字 才能执行
542					if CHINESE_PURE_NUMBER_LIST
543						.iter()
544						.any(|&x| x == temp_new_ch_number_string_list[i].to_string().as_str())
545					{
546						per_count_switch = true;
547					} else {
548						per_count_switch = false;
549						//有一个不合适 退出循环
550						break;
551					}
552				}
553				if per_count_switch {
554					let temp_left_part_string: String =
555						temp_new_ch_number_string_list[0..1].iter().collect();
556					let temp_right_part_string: String =
557						temp_new_ch_number_string_list[1..].iter().collect();
558					new_ch_number_string_list =
559						temp_left_part_string + "分之" + &temp_right_part_string;
560				}
561			}
562			None => {}
563		}
564	}
565
566	return new_ch_number_string_list;
567}
568
569//检查初次提取的汉字数字是正负号是否切分正确
570fn check_sign_seg(chinese_number_list: &Vec<String>) -> Vec<String> {
571	let mut new_chinese_number_list: Vec<String> = vec![];
572	let mut temp_sign = "".to_string();
573	for i in 0..chinese_number_list.len() {
574		// #新字符串 需要加上上一个字符串 最后1位的判断结果
575		let mut new_ch_number_string = temp_sign.clone() + &chinese_number_list[i];
576		let temp_chinese_number_list: Vec<char> = new_ch_number_string.chars().collect();
577		if temp_chinese_number_list.len() > 1 {
578			let last_string: String = temp_chinese_number_list
579				[(temp_chinese_number_list.len() - 1)..]
580				.iter()
581				.collect();
582			// #如果最后1位是百分比 那么本字符去掉最后三位  下一个数字加上最后1位
583			if CHINESE_SIGN_LIST.iter().any(|&x| x == last_string.as_str()) {
584				temp_sign = last_string;
585				// #如果最后1位 是  那么截掉最后1位
586				// let tempWithoutLastPartString:String =
587				new_ch_number_string = temp_chinese_number_list
588					[..(temp_chinese_number_list.len() - 1)]
589					.iter()
590					.collect();
591			} else {
592				temp_sign = "".to_string();
593			}
594		}
595		new_chinese_number_list.push(new_ch_number_string)
596	}
597	return new_chinese_number_list;
598}
599
600pub struct C2DResultStruct {
601	pub input_text: String,
602	pub replaced_text: String,
603	pub ch_number_string_list: Vec<String>,
604	pub digits_string_list: Vec<String>,
605}
606
607// static TAKING_CHINESE_DIGITS_MIX_RE_RULES_STRING: &str = r#"(?:(?:分之){0,1}(?:\+|\-){0,1}[正负]{0,1})(?:(?:(?:\d+(?:\.\d+){0,1}(?:[\%]){0,1}
608// |\.\d+(?:[\%]){0,1}){0,1}(?:(?:(?:[一二三四五六七八九十千万亿兆幺零百]+(?:点[一二三四五六七八九万亿兆幺零]+){0,1})|(?:点[一二三四五六七八九万亿兆幺零]+))))
609// |(?:(?:\d+(?:\.\d+){0,1}(?:[\%]){0,1}|\.\d+(?:[\%]){0,1})(?:(?:(?:[一二三四五六七八九十千万亿兆幺零百]+
610// 	(?:点[一二三四五六七八九万亿兆幺零]+){0,1})|(?:点[一二三四五六七八九万亿兆幺零]+))){0,1}))"#;
611//rust  % 号不能加转义
612static TAKING_CHINESE_DIGITS_MIX_RE_RULES_STRING: &str = concat!(
613	r#"(?:(?:分之){0,1}(?:\+|\-){0,1}[正负]{0,1})(?:(?:(?:\d+(?:\.\d+){0,1}(?:[%‰‱]){0,1}"#,
614	r#"|\.\d+(?:[%‰‱]){0,1}){0,1}(?:(?:(?:[一二三四五六七八九十千万亿兆幺零百]+(?:点[一二三四五六七八九万亿兆幺零]+){0,1})"#,
615	r#"|(?:点[一二三四五六七八九万亿兆幺零]+))))|(?:(?:\d+(?:\.\d+){0,1}(?:[%‰‱]){0,1}|\.\d+(?:[%‰‱]){0,1})"#,
616	r#"(?:(?:(?:[一二三四五六七八九十千万亿兆幺零百]+"#,
617	r#"(?:点[一二三四五六七八九万亿兆幺零]+){0,1})|(?:点[一二三四五六七八九万亿兆幺零]+))){0,1}))"#
618);
619
620static CHINESE_SIGN_DICT_STATIC: [(&str, &str); 4] =
621	[("负", "-"), ("正", "+"), ("-", "-"), ("+", "+")];
622
623static CHINESE_CONNECTING_SIGN_STATIC: [(&str, &str); 3] = [(".", "."), ("点", "."), ("·", ".")];
624
625// ChineseToDigits 是可以识别包含百分号,正负号的函数,并控制是否将百分之10转化为0.1
626fn chinese_to_digits(chinese_chars_to_trans: String, percent_convert: bool) -> String {
627	// """
628	// 分之  分号切割  要注意
629	// """
630	let mut final_total: String;
631	let mut convert_result_list: Vec<String> = vec![];
632	let mut chinese_chars_list_by_div: Vec<String> = vec![];
633
634	let chinese_sign_dict: HashMap<&str, &str> = CHINESE_SIGN_DICT_STATIC.into_iter().collect();
635	let chinese_connecting_sign_dict: HashMap<&str, &str> =
636		CHINESE_CONNECTING_SIGN_STATIC.into_iter().collect();
637
638	if chinese_chars_to_trans.contains("分之") {
639		let temp_split_result: Vec<&str> = chinese_chars_to_trans.split("分之").collect();
640		for s in temp_split_result {
641			chinese_chars_list_by_div.push(s.to_string());
642		}
643	} else {
644		chinese_chars_list_by_div.push(chinese_chars_to_trans);
645	}
646
647	for k in 0..chinese_chars_list_by_div.len() {
648		let mut temp_chinese_char: String = chinese_chars_list_by_div[k].to_string();
649
650		// chinese_char := temp_chinese_char
651		let chinese_char: Vec<char> = temp_chinese_char.chars().collect();
652		// """
653		// 看有没有符号
654		// """
655		let mut sign = "".to_string();
656		let mut char_to_get: String;
657		for i in 0..chinese_char.len() {
658			char_to_get = chinese_char[i].to_string();
659			let value = chinese_sign_dict.get(char_to_get.as_str());
660			match value {
661				Some(value) => {
662					sign = value.to_string();
663					// chineseCharsToTrans = strings.Replace(chineseCharsToTrans, charToGet, "", -1)
664					temp_chinese_char = temp_chinese_char.replace(&char_to_get, "");
665				}
666				None => {}
667			}
668		}
669		// chinese_char = []rune(chineseCharsToTrans)
670
671		// """
672		// 小数点切割,看看是不是有小数点
673		// """
674		let mut string_contain_dot = false;
675		let mut left_of_dot_string = "".to_string();
676		let mut right_of_dot_string = "".to_string();
677		for (key, _) in &chinese_connecting_sign_dict {
678			if temp_chinese_char.contains(&key.to_string()) {
679				let chinese_chars_dot_split_list: Vec<&str> =
680					temp_chinese_char.split(key).collect();
681				left_of_dot_string = chinese_chars_dot_split_list[0].to_string();
682				right_of_dot_string = chinese_chars_dot_split_list[1].to_string();
683				string_contain_dot = true;
684				break;
685			}
686		}
687		let mut convert_result: String;
688		if !string_contain_dot {
689			convert_result = core_ch_to_digits(temp_chinese_char);
690		} else {
691			// convert_result = "".to_string();
692			let mut temp_buf: String;
693			let temp_right_digits: String;
694			// #如果小数点右侧有 单位 比如 2.55万  4.3百万 的处理方式
695			// #先把小数点右侧单位去掉
696			let mut temp_count_string = "".to_string();
697			let list_of_right: Vec<char> = right_of_dot_string.chars().collect();
698			for ii in (0..(list_of_right.len())).rev() {
699				let _find_counting_unit_index_result = CHINESE_PURE_COUNTING_UNIT_LIST
700					.iter()
701					.position(|&x| x == list_of_right[ii].to_string().as_str());
702				match _find_counting_unit_index_result {
703					Some(_find_counting_unit_index_result) => {
704						temp_count_string = list_of_right[ii].to_string() + &temp_count_string;
705					}
706					None => {
707						right_of_dot_string = list_of_right[0..(ii + 1)].iter().collect();
708						break;
709					}
710				}
711			}
712
713			let mut temp_count_num = 1.0;
714			if temp_count_string != "" {
715				let temp_num = core_ch_to_digits(temp_count_string).parse::<f32>().unwrap();
716				temp_count_num = temp_num;
717			}
718
719			if left_of_dot_string == "" {
720				// """
721				// .01234 这种开头  用0 补位
722				// """
723				temp_buf = "0.".to_string();
724				temp_right_digits = core_ch_to_digits(right_of_dot_string);
725				temp_buf = temp_buf + &temp_right_digits;
726				convert_result = temp_buf;
727			} else {
728				temp_buf = core_ch_to_digits(left_of_dot_string);
729				temp_buf = temp_buf + ".";
730				temp_right_digits = core_ch_to_digits(right_of_dot_string);
731				temp_buf = temp_buf + &temp_right_digits;
732				convert_result = temp_buf;
733			}
734
735			let temp_str_to_float = convert_result.parse::<f32>().unwrap();
736			convert_result = (temp_str_to_float * temp_count_num).to_string();
737		}
738		//如果转换结果为空字符串 则为百分之10 这种
739		if convert_result == "" {
740			convert_result = "1".to_string();
741		}
742		convert_result = sign + &convert_result;
743		// #最后在双向转换一下 防止出现 0.3000 或者 00.300的情况
744
745		let new_convert_result_temp: Vec<char> = convert_result.chars().collect();
746		let new_buf: String;
747		if convert_result.ends_with(".0") {
748			new_buf = new_convert_result_temp[0..new_convert_result_temp.len() - 2]
749				.iter()
750				.collect();
751		} else {
752			new_buf = convert_result;
753		}
754		convert_result_list.push(new_buf);
755	}
756	if convert_result_list.len() > 1 {
757		// #是否转换分号及百分比
758		if percent_convert {
759			// let temp_float1 = convert_result_list[1].parse::<f32>().unwrap();
760			// let temp_float0 = convert_result_list[0].parse::<f32>().unwrap();
761			// // fmt.Println(tempFloat1 / tempFloat0)
762			// final_total = (temp_float1 / temp_float0).to_string();
763			let temp_float1 = Decimal::from_str(&convert_result_list[1]).unwrap();
764			let temp_float0 = Decimal::from_str(&convert_result_list[0]).unwrap();
765			final_total = (temp_float1 / temp_float0).to_string();
766		} else {
767			if convert_result_list[0] == "100" {
768				final_total = convert_result_list[1].to_string() + "%"
769			} else if convert_result_list[0] == "1000" {
770				final_total = convert_result_list[1].to_string() + "‰"
771			} else {
772				final_total = convert_result_list[1].to_string() + "/" + &convert_result_list[0]
773			}
774		}
775	} else {
776		final_total = convert_result_list[0].to_string()
777		//最后再转换一下 防止出现 .50 的问题  不能转换了 否则  超出精度了………… 服了  5亿的话
778		// tempFinalTotal, err3 := strconv.ParseFloat(finalTotal, 32)
779		// if err3 != nil {
780		// 	panic(err3)
781		// } else {
782		// 	finalTotal = strconv.FormatFloat(tempFinalTotal, 'f', -1, 32)
783		// }
784	}
785	//删除最后的0
786	if final_total.contains("."){
787		final_total = final_total.trim_end_matches("0").to_string();
788		final_total = final_total.trim_end_matches(".").to_string();
789	}
790	
791
792	return final_total;
793}
794
795// 将句子中的汉子数字提取的整体函数
796/// Will extract the chinese and digits number together from string. and return the convert result
797/// 
798/// Returns `C2DResultStruct`  data struct
799/// ```
800/// pub struct C2DResultStruct {
801///		pub input_text: String,
802///		pub replaced_text: String,
803///		pub ch_number_string_list: Vec<String>,
804///		pub digits_string_list: Vec<String>,
805/// }
806/// ```
807///
808///
809/// [`chText`]: chinese string
810/// 
811/// [`percentConvert`]: convert percent simple. Default is True.  3% will be 0.03 in the result
812/// 
813/// [`traditionalConvert`]: Switch to convert the Traditional Chinese character to Simplified chinese
814/// 
815/// # Examples
816///
817/// Basic usage:
818///
819/// ```
820/// use chinese2digits::take_number_from_string;
821/// 
822/// let string_example = "百分之5负千分之15".to_string();
823/// let test_result = take_number_from_string(&string_example, true, true);
824/// assert_eq!(test_result.replaced_text, "0.05-0.015");
825///	assert_eq!(test_result.ch_number_string_list, vec!["百分之5", "负千分之15"]);
826///	assert_eq!(test_result.digits_string_list, vec!["0.05", "-0.015"]);
827/// ```
828/// 
829fn take_chinese_number_from_string(
830	ch_text_string: &str,
831	percent_convert: bool,
832	traditional_convert: bool,
833) -> C2DResultStruct {
834	let mut ch_number_string_list: Vec<String> = vec![];
835
836	//默认参数设置
837	// if len(opt) > 3 {
838	// 	panic("too many arguments")
839	// }
840
841	// var percentConvert bool
842	// var traditionalConvert bool
843	// // var digitsNumberSwitch bool
844	// // digitsNumberSwitch := false
845
846	// switch len(opt) {
847	// case 1:
848	// 	percentConvert = opt[0].(bool)
849	// 	traditionalConvert = true
850	// 	// digitsNumberSwitch = false
851	// case 2:
852	// 	percentConvert = opt[0].(bool)
853	// 	traditionalConvert = opt[1].(bool)
854	// 	// digitsNumberSwitch = false
855	// // case 3:
856	// // 	percentConvert = opt[0].(bool)
857	// // 	traditionalConvert = opt[1].(bool)
858	// // digitsNumberSwitch = opt[2].(bool)
859	// default:
860	// 	percentConvert = true
861	// 	traditionalConvert = true
862	// }
863
864	// fmt.Println(digitsNumberSwitch)
865
866	//"""
867	//简体转换开关
868	//"""
869	// originText := chTextString
870
871	// let traditionalConvert = true;
872	let converted_string: String =
873		traditional_text_convert_func(&ch_text_string.to_string(), traditional_convert);
874
875	//正则引擎
876	let mut reg_match_result: Vec<String> = vec![];
877	let taking_chinese_digits_mix_re_rules: Regex =
878		Regex::new(TAKING_CHINESE_DIGITS_MIX_RE_RULES_STRING).unwrap();
879	//PCRE2 引擎,但是正则断句不对导致字符串切割总是失败。
880	// for cap in taking_chinese_digits_mix_re_rules.captures_iter(&converted_string.as_bytes()) {
881	// 	let caps = cap.unwrap();
882	// 	let cap_result = str::from_utf8(&caps[0]);
883	// 	match cap_result{
884	// 		Ok(cap_result) => {
885	// 			reg_match_result.push(cap_result.to_string());
886	// 		}
887	// 		Err(cap_result) =>{
888	// 			println!("{}",cap_result)
889	// 		}
890
891	// 	}
892
893	// }
894
895	// let caps=taking_chinese_digits_mix_re_rules.captures(&converted_string.as_bytes()).unwrap();
896
897	// match caps{
898	// 	Some(caps)=>{
899	// 		for i in 0..caps.len(){
900	// 			let cap = caps.get(i).unwrap();
901	// 			let cap_result = str::from_utf8(cap.as_bytes());
902	// 			match cap_result{
903	// 				Ok(cap_result)=>{
904	// 					println!("{}",cap_result.to_string());
905	// 					reg_match_result.push(cap_result.to_string());
906	// 				}
907	// 				Err(cap_result) =>{
908	// 					println!("error is {}",cap_result);
909	// 				}
910	// 			}
911
912	// 		}
913
914	// 	}
915	// 	None=>{
916
917	// 	}
918	// }
919
920	// println!("Values inside vec: {:?}", reg_match_result);
921	for cap in taking_chinese_digits_mix_re_rules.captures_iter(&converted_string) {
922		reg_match_result.push(cap[0].to_string());
923	}
924
925	let mut temp_text: String;
926	let mut ch_number_string_list_temp: Vec<String> = vec![];
927	for i in 0..reg_match_result.len() {
928		temp_text = reg_match_result[i].to_string();
929		ch_number_string_list_temp.push(temp_text);
930	}
931	// println!("Values inside ch_number_string_list_temp: {:?}", ch_number_string_list_temp);
932	// ##检查是不是  分之 切割不完整问题
933	ch_number_string_list_temp = check_number_seg(&ch_number_string_list_temp, &converted_string);
934
935	// 检查最后是正负号的问题
936	ch_number_string_list_temp = check_sign_seg(&ch_number_string_list_temp);
937
938	// #备份一个原始的提取,后期处结果的时候显示用
939	let origin_ch_number_take: Vec<String> = ch_number_string_list_temp.clone();
940
941	// #将阿拉伯数字变成汉字  不然合理性检查 以及后期 如果不是300万这种乘法  而是 四分之345  这种 就出错了
942	ch_number_string_list_temp = digits_to_ch_chars(&ch_number_string_list_temp);
943
944	//检查合理性 是否是单纯的单位  等
945	// var chNumberStringList []string
946	// var originCHNumberForOutput []string
947	let mut origin_ch_number_for_output: Vec<String> = vec![];
948	for i in 0..ch_number_string_list_temp.len() {
949		// fmt.Println(aa[i])
950		temp_text = ch_number_string_list_temp[i].to_string();
951		if check_chinese_number_reasonable(&temp_text) {
952			// #如果合理  则添加进被转换列表
953			ch_number_string_list.push(temp_text);
954			// #则添加把原始提取的添加进来
955			origin_ch_number_for_output.push(origin_ch_number_take[i].to_string());
956		}
957		// CHNumberStringList = append(CHNumberStringList, regMatchResult[i][0])
958	}
959
960	// """
961	// 进行标准汉字字符串转换 例如 二千二  转换成二千零二
962	// """
963	ch_number_string_list_temp = vec![];
964	for i in 0..ch_number_string_list.len() {
965		ch_number_string_list_temp.push(standard_ch_number_convert(
966			ch_number_string_list[i].to_string(),
967		));
968	}
969
970	//"""
971	//将中文转换为数字
972	//"""
973	let mut digits_string_list: Vec<String> = vec![];
974	let mut replaced_text = converted_string;
975	let mut temp_ch_to_digits_result: String;
976	if ch_number_string_list_temp.len() > 0 {
977		for i in 0..ch_number_string_list_temp.len() {
978			temp_ch_to_digits_result =
979				chinese_to_digits(ch_number_string_list_temp[i].to_string(), percent_convert);
980			digits_string_list.push(temp_ch_to_digits_result);
981		}
982		// 按照 中文数字字符串长度 的逆序排序
983		// println!("Values inside origin digits_string_list: {:?}", digits_string_list);
984
985		let mut tuple_to_replace: Vec<_> = origin_ch_number_for_output
986			.iter()
987			.zip(digits_string_list.iter())
988			.enumerate()
989			.collect();
990
991		tuple_to_replace.sort_by_key(|(_, (_, z))| z.chars().count());
992
993		// digits_string_list.sort_by_key(|x| x.chars().count());
994		//自动逆序 不需要 reverse()
995		// digits_string_list.reverse();
996
997		// println!("Values inside digits_string_list: {:?}", digits_string_list);
998		// println!("replaced text is {}",replaced_text);
999		// println!("Values inside origin_ch_number_for_output: {:?}", origin_ch_number_for_output);
1000		//"""
1001		//按照提取出的中文数字字符串长短排序,然后替换。防止百分之二十八 ,二十八,这样的先把短的替换完了的情况
1002		//"""
1003		for i in 0..digits_string_list.len() {
1004			// replaced_text = replaced_text.replace(
1005			// 	&origin_ch_number_for_output[i].to_string(),
1006			// 	&digits_string_list[i].to_string(),
1007			// );
1008			replaced_text = replaced_text.replace(
1009				tuple_to_replace[i].1 .0, //&origin_ch_number_for_output[i]
1010				tuple_to_replace[i].1 .1, //&digits_string_list[i]
1011			);
1012		}
1013	}
1014
1015	let final_result = C2DResultStruct {
1016		input_text: ch_text_string.to_string(),
1017		replaced_text: replaced_text.to_string(),
1018		ch_number_string_list: origin_ch_number_for_output,
1019		digits_string_list: digits_string_list,
1020	};
1021	return final_result;
1022}
1023
1024pub fn take_number_from_string(
1025	ch_text_string: &str,
1026	percent_convert: bool,
1027	traditional_convert: bool,
1028) -> C2DResultStruct {
1029	//默认参数设置
1030
1031	// let percent_convert = true;
1032	// let traditional_convert = true;
1033	let final_result: C2DResultStruct =
1034		take_chinese_number_from_string(ch_text_string, percent_convert, traditional_convert);
1035	return final_result;
1036}
1037
1038#[test]
1039fn test_core_ch_to_digits() {
1040	// do test work
1041	assert_eq!(core_ch_to_digits("三百四十二万".to_string()), "3420000")
1042}
1043#[test]
1044fn test_check_number_seg() {
1045	let a1 = vec![
1046		"百".to_string(),
1047		"分之5".to_string(),
1048		"负千".to_string(),
1049		"分之15".to_string(),
1050	];
1051	let a2 = "百分之5负千分之15".to_string();
1052	let a3 = vec!["百分之5".to_string(), "负千分之15".to_string()];
1053	assert_eq!(check_number_seg(&a1, &a2), a3)
1054}
1055
1056#[test]
1057fn test_check_chinese_number_reasonable() {
1058	let a2 = "千千万万".to_string();
1059	assert_eq!(check_chinese_number_reasonable(&a2), false)
1060}