scala通过尾递归解析提取字段信息
一、背景
获取数据中以“|”作为字段间的分隔符,但个别字段中数据也是以“|”作为分隔符。因此,在字段提取时需要保护数据完整性。
二、实现
1.数据以“|”分隔,可以采用递归方式迭代解析。通过尾递归方式降低运行风险;
2.尾递归中使用模式匹配;
3.解析时,根据separator做遍历,“‘”和“’”(一对引号之间的数据作为一个整体cell),引号前数据位head(即使为空,也可以),cell后的数据由下一次迭代解析,则整个结构为:result+head+cell(引号间的数据)+(head+cell+(head+cell+(...)))
4.默认数据中引号成对出现;
5.具体实现如下:
1 val input="123||abc||lat|||'120.15|34.56'||lon||'112.135|30.124'|location|grid|'101|26|37'|0755|x|" 2 3 def separator(str:String,sep:String,result:Array[String]):Array[String]={str.indexOf(sep) match{ 4 case v if v<0 =>result++str.split("\\|",-1) 5 case x =>{ 6 val head=str.substring(0,x).stripSuffix("|").split("\\|",-1) 7 val next=str.substring(x+1).indexOf(sep) 8 val cell=Array(str.substring(x+1,x+next+1).replaceAll("\\|",",")) 9 separator(str.substring(x+next+3),sep,result++head++cell)} 10 }} 11 12 println(separator(input,"'",Array()).toList)
三、总结
1.使用尾递归时,要保证每次迭代要有结果作为下次迭代的输入;
2.substring提取子字符串时为前闭后开;
3.字符串做split时尽量使用index=-1,保证||之间为一个空的数据,但不能丢弃;
4.replaceAll替换字符时,注意".$|()[{^?*+\\"需要做转译;
5.保证|‘不会产生多余空元素,需要对head的字符串做stripSuffix去除动作。