需求
自己试图写个解析章节名对章节排序的功能,然后发现章节名是类似:“第一千二十一章 过去”这种的中文,不能直接转int,然后就试着自己写了下
实现思路
参考:JAVA中文数字转换为数值
思路其实挺简单的,数字分为俩种,0-9是数值,十/百/千这些是位值,循环读取第一位,读取到数时暂存,读到位时进行处理看位是否大于之前的所有,大于则相加后相乘,小于则于前一个数值相乘后相加。
代码实现
/**
* 通过章节名获取第几章
* @param title 章节名
* @return 转换后的int
*/
public static int getSectionNum(String title){
String sectionNumString = title.substring(title.indexOf("第")+1,title.indexOf("章"))
.replace(" ","");
char[] charList = sectionNumString.toCharArray();
int num = getChinaNum(charList,0,0,0);
return num;
}
/**
* 通过递归将中文转int
* @param chinaList 需要转换的中文数值
* @param i 处理到的位数
* @param maxNum 暂存的数字
* @param nowNum 暂存的数字
* @return 转换后的int
*/
public static int getChinaNum(char[] chinaList,int i,int maxNum,int nowNum){
if(i>=chinaList.length){
return maxNum;
}
int flag = charToInt(chinaList[i]);
i++;
if(flag>9){
// 这里时解决第一位不是数值而是位值得情况
maxNum = maxNum == 0 ? 1:maxNum;
if(flag > maxNum){
// todo 这个if有俩次递归,或许会有更好的处理方式
if(getChinaNum(chinaList,i,0,0)>(maxNum+nowNum)*flag){
return getChinaNum(chinaList,i,(maxNum+nowNum)*flag,0);
}else{
return (maxNum+nowNum)*flag + getChinaNum(chinaList,i,0,0);
}
}else{
return getChinaNum(chinaList,i,maxNum+nowNum*flag,0);
}
}else{
if(maxNum < flag){
return getChinaNum(chinaList,i,flag,0);
}else{
return getChinaNum(chinaList,i,maxNum,flag);
}
}
}
/**
* 单个字符转int
* @param num 需要转换的字符
* @return 转换后的int
*/
public static int charToInt(char num){
switch (num){
case '十':
return 10;
case '百':
return 100;
case '千':
return 1000;
case '万':
return 10000;
case '亿':
return 100000000;
case '零':
return 0;
case '一':
return 1;
case '二':
return 2;
case '两':
return 2;
case '三':
return 3;
case '四':
return 4;
case '五':
return 5;
case '六':
return 6;
case '七':
return 7;
case '八':
return 8;
case '九':
return 9;
default:
System.out.println(num);
return 0;
}
}
可优化点
- switch里面得字符不是那么全,比如金额的壹贰叁这些就没有加进去,因为我的需求只是章节名
- 用的是int有21亿多的上限,还是那个问题,我需求不到
- 中间有一段用todo标出来的,进行了俩段递归,性能消耗比较大,但是我暂时没想到怎么处理
最后
写完发现解析章节名失败,跑完发现不是所有章节都有“第X章”,比如完结感言之类,这种还章节能直接跳过,但是有的存在分卷情况,俩卷之间第X章可能重复,等于白写,记录下,或许以后能用到吧