IOS/Android开发用递归法获取指定开始字符串到结尾字符串中间内容

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_16674697/article/details/56016325

前言

最近在做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中通过正则法和递归分割法的运行耗时可以看到,除了第一次加载,相差很大,其余性能上相差无几,安卓也是.之所以我会选择使用递归法,毕竟是自己对于逻辑上的一个大胆尝试,对于算法类来说,递归只是一个基础,如果可以真正的融入到以后的代码生涯中,相信会是一个不错的锻炼.


猜你喜欢

转载自blog.csdn.net/qq_16674697/article/details/56016325
今日推荐