1. 程式人生 > >IOS/Android開發用遞迴法獲取指定開始字串到結尾字串中間內容

IOS/Android開發用遞迴法獲取指定開始字串到結尾字串中間內容

前言

最近在做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中通過正則法和遞迴分割法的執行耗時可以看到,除了第一次載入,相差很大,其餘效能上相差無幾,安卓也是.之所以我會選擇使用遞迴法,畢竟是自己對於邏輯上的一個大膽嘗試,對於演算法類來說,遞迴只是一個基礎,如果可以真正的融入到以後的程式碼生涯中,相信會是一個不錯的鍛鍊.