IOS/Android開發用遞迴法獲取指定開始字串到結尾字串中間內容
阿新 • • 發佈:2019-02-10
前言
最近在做ios開發的時候,突然遇到了一個需求,感覺挺有意思的就拿出來記錄一下.效果圖是這樣的:
乍一看,就是幾個特殊關鍵字變色嘛,沒什麼難的,我原本以為後臺的介面會把要變色的關鍵字單獨給我個欄位,裡面儲存一個變色字元陣列,可是當我拿到介面的時候,挺懵逼的,因為後臺給我的格式是這樣的:
返回格式還是比較複雜的,不過也不難理解."#c_y_s#"代表以要標黃色(yellow)欄位的開頭,"#c_y_e#"同理為結束,要標黃的欄位為兩個:"確定檔期"、"預留檔期"、"上午會議"和"下午會議".
這個格式的解析有很多方法,在這裡我列舉兩個效率比較高效的方法作為比較:
一、正則法
IOS:
-(NSMutableArray *)getArrayWithStr:(NSString *)str andStartStr:(NSString *)start andEndStr:(NSString *)end andArray:(NSMutableArray *)resultArr{ NSRegularExpression *regex =[NSRegularExpression regularExpressionWithPattern: [NSString stringWithFormat:@"%@|%@",start,end] options:0 error:nil]; NSMutableArray* rangeArr=[[NSMutableArray alloc] init]; for (NSTextCheckingResult* match in [regex matchesInString:str options:0 range:NSMakeRange(0, str.length)]) { [rangeArr addObject:[NSValue valueWithRange:match.range]];//找到每個分號和冒號的Range,存到陣列 } for (int i=0; i<rangeArr.count; i=i+2) {//for迴圈獲取到每個符合條件的字串,i=i+2將相鄰的冒號和分號配對 NSRange range=[[rangeArr objectAtIndex:i] rangeValue]; NSInteger location=range.location; NSRange nextRange=[[rangeArr objectAtIndex:i+1] rangeValue]; NSInteger nextLocation=nextRange.location; NSRange finalRange=NSMakeRange(range.location+start.length, nextLocation-location-start.length); NSString* finalStr=[str substringWithRange:finalRange]; [resultArr addObject:finalStr]; } return resultArr; }
執行耗時:
Android:
//正則法獲取 private ArrayList<String> getList2(String str, String start, String end,ArrayList<String> list){ Matcher slashMatcher = Pattern.compile(start).matcher(str); Matcher slashMatcher2 = Pattern.compile(end).matcher(str); while (slashMatcher.find()) { slashMatcher2.find(); list.add(str.substring(slashMatcher.start() + start.length(),slashMatcher2.start())); } return list; }
執行耗時:
原理:
通過正則匹配查詢關鍵字的索引位置,然後通過迴圈返回對應特殊標識間的字元,組成陣列
二、字串遞迴分割法(自創)
IOS:
-(NSMutableArray *)getArrayWithStr:(NSString *)str andStartStr:(NSString *)start andEndStr:(NSString *)end
andArray:(NSMutableArray *)resultArr{
NSArray *firstArr = [str componentsSeparatedByString:start];
if(firstArr.count!=1){//如果找到開始符號
NSString * leftStr=[str substringFromIndex:((NSString*)firstArr[0]).length+start.length];
NSArray *nextArr = [leftStr componentsSeparatedByString:end];
if(nextArr.count!=1){//找到結尾符號
[resultArr addObject:nextArr[0]];//新增第一個
leftStr=[str substringFromIndex:((NSString*)firstArr[0]).length+((NSString*)nextArr[0]).length+start.length+end.length];
[resultArr addObjectsFromArray:
[self getArrayWithStr:leftStr andStartStr:start andEndStr:end andArray:[NSMutableArray array]]];//新增剩下的
}
}
return resultArr;
}
執行耗時:
Android:
/**
* 遞迴分割法
* @param str 原始字串
* @param start 特殊欄位開始標誌符
* @param end 特殊欄位結束標誌符
* @param list 需要新增的陣列
* @return
*/
public ArrayList<String> getList(String str,String start,String end,ArrayList<String> list){
String[] firstArr=str.split(start);
if(firstArr.length>1||str.endsWith(start)){
String leftStr=str.substring(firstArr[0].length()+start.length());
String[] nextArr=leftStr.split(end);
if(nextArr.length>1||str.endsWith(end)){
leftStr=str.substring(firstArr[0].length()+nextArr[0].length()+start.length()+end.length(),str.length());
list.add(nextArr[0]);
if(leftStr.contains(start)){
list.addAll(getList(leftStr,start,end,new ArrayList<String>()));
}
}
}
return list;
}
執行耗時:
原理:
通過遞迴方式不斷的分割出指定字元的位置,在這裡安卓和IOS在分割函式上有一點區別,IOS中分割函式componentsSeparatedByString如果原始字串結尾是分割符號,則會自動生成@""空項,陣列個數為2.但是安卓中用split分割函式,如果原始字串作為結尾,將返回原來字串,個數為1.因此,在安卓中需要單獨加入判斷endsWith來確保資料的正確性.
總結:
IOS中通過正則法和遞迴分割法的執行耗時可以看到,除了第一次載入,相差很大,其餘效能上相差無幾,安卓也是.之所以我會選擇使用遞迴法,畢竟是自己對於邏輯上的一個大膽嘗試,對於演算法類來說,遞迴只是一個基礎,如果可以真正的融入到以後的程式碼生涯中,相信會是一個不錯的鍛鍊.