记一次解析字符串:在目标字符串中找出指定的N个字符串所在的起始位置
我们的项目上有一个这样的场景:一个下拉选择框,同时要支持用户输入,将最终的结果显示在文本框中(就是普通的字符串,用户在下拉框中选择的放在【】中)……不知道能不能想象出来,写上一篇笔记的时候发现和咱们博客园选择“tag 标签”的功能有点接近啊,我们的ui还是跟她有些不同。
还是拿一个具体的例子说一下吧。下拉框中有“姓名”、“年龄”两个选择项,你可以选择也可以自己在文本框中输入,例如文本框中的内容是:自定义001【姓名】自定义002【年龄】自定义003。我们要做的就是解析这个字符串,我们需要识别出其中的“姓名”和“年龄”(无论是用户选择的,还是用户输入的),最后的结果应该是这样的 ["自定义001","【姓名】","自定义002","【年龄】","自定义003"]。
这里还要在补充一点他们的要求:就是可以同时匹配多个时候(开始的索引位置相同,但是结尾不同),我们需要识别下拉列表中的第一个。有点抽象,还是说一个例子吧。这里下拉列表中有“姓名】”和“姓名”两个,这时候文本框中的内容是:自定义001【姓名】】自定义002。交换下拉列表中的顺序,最终得到的结果是不一样的。
说了这么一大推,感觉好没意思啊!其实还是蛮有意思的(解析这个)。遇到这个问题之后最先想到的就是,遍历下拉框数组,利用indexof查找看看有没有,之后截取三部分(前面的、自己、后面的),之后递归处理前面和后面的部分。我去,想着简单但是写的时候好费劲啊!最后查了一下,看看有没有这种方法,在目标字符串中找出指定的n个字符串的所在起始位置,一个方法可以搞定的那种,最后还是正则表达式救了我。现在我可以得到下拉选项中的每一项在目标字符串的起始位置了,剩下的就是利用这些起始位置去截取目标字符串了,脑袋一热将这些这些索引位置放到一个数组中(去重),之后排序,之后两两已截取不就完了,这样写完之后就真的凉凉了,很多字符串都解析错误,之后弄了好几版都不行,决定静下来分析一下,看看到底有多少种情况。之前竟然还想到数据去重(确实是第一次写就去重了),但是就没有想想什么情况下有重复的情况出现:索引开始相同,某一个的索引结束是另一个的开始……后来我直接画图了,列出了12中情况,在下面可以在纸上画,这里呢?我也又找到了一个神器:,你看一下:
一共有12中情况,要是一个一个if else 太费劲了,细看一下发现中间的8种情况是有问题的,如果将这8种情况下的起始索引都放到数组中去截取字串,那么他就会将下拉框中的下拉项(也就是图中两个中的一个截断),所以呢用了一下排除法。之后呢,为了验证我也列举了上面的6中情况(下面分别给出例子),感觉前面的6个和后面的6个是对称的……
// 参考: // https://developer.mozilla.org/zh-cn/docs/web/javascript/reference/global_objects/regexp/@@matchall // https://developer.mozilla.org/zh-cn/docs/web/javascript/reference/global_objects/string/matchall // 待选列表(下拉列表项) var tobeselectedlist = [{ dispalyname: "姓名", dispalyindex: "name1" }, { dispalyname: "年龄", dispalyindex: "age" }, { dispalyname: "姓【名", dispalyindex: "name2" }, { dispalyname: "名】001", dispalyindex: "name3" }, { dispalyname: "【姓名", dispalyindex: "name4" }, { dispalyname: "1【姓名】1", dispalyindex: "name5" }, { dispalyname: "姓名】", dispalyindex: "name6" } ]; var tempdispalynamearr = tobeselectedlist.map(function (item) { return item.dispalyname; }); // 解析方法 var gettargetarrbyuserinputandfilterstrs = function (userinputstr, filterstrs) { var tempindexposarr = [], tempindexposobjarr = [], tempfilterstraddcharobj = {}; filterstrs.foreach(function (filterstr, index) { var tempkey = '【' + filterstr + '】', tempregexp = new regexp(tempkey, 'g'), match; tempfilterstraddcharobj[tempkey] = filterstr; while ((match = tempregexp.exec(userinputstr)) !== null) { var tempfilterposarrs = tempindexposobjarr.filter(function (startandlastindexitem) { // return (match.index >= startandlastindexitem.index && match.index < startandlastindexitem.lastindex) || // (match.index < startandlastindexitem.index && tempregexp.lastindex >= startandlastindexitem.lastindex); return !(tempregexp.lastindex <= startandlastindexitem.index || match.index >= startandlastindexitem.lastindex); }); if (tempfilterposarrs.length === 0) { tempindexposobjarr.push({ index: match.index, lastindex: tempregexp.lastindex }); } } }); tempindexposobjarr.foreach(function (indexobj) { if (tempindexposarr.indexof(indexobj.index) < 0) { tempindexposarr.push(indexobj.index); } if (tempindexposarr.indexof(indexobj.lastindex) < 0) { tempindexposarr.push(indexobj.lastindex); } }); if (tempindexposarr.indexof(0) < 0) { tempindexposarr.push(0); } if (tempindexposarr.indexof(userinputstr.length) < 0) { tempindexposarr.push(userinputstr.length); } tempindexposarr = tempindexposarr.sort(function (a, b) { return a - b; }); var lastneedarr = []; tempindexposarr.foreach(function (posindex, index) { if (index < tempindexposarr.length - 1) { var tempisonefilterstr = userinputstr.substring(posindex, tempindexposarr[index + 1]); // if(tempfilterstraddcharobj.hasownproperty(tempisonefilterstr)){ // tempisonefilterstr=tempfilterstraddcharobj[tempisonefilterstr] // } lastneedarr.push(tempisonefilterstr); } }); return lastneedarr; }; // 等待解析的字符串(也就是用户选择或者输入的最终结果) var waitanalysisstr1 = "自定义001【姓名】自定义002【年龄】自定义003"; var tobeselectedlist1_1 = ["姓名", "年龄"]; // ["自定义001","【姓名】","自定义002","【年龄】","自定义003"] var tobeselectedlist1_2 = ["年龄", "姓名"]; // ["自定义001","【姓名】","自定义002","【年龄】","自定义003"] var waitanalysisstr2 = "自定义001【姓名】【年龄】自定义002"; var tobeselectedlist2_1 = ["姓名", "年龄"]; // ["自定义001","【姓名】","【年龄】","自定义002"] var tobeselectedlist2_2 = ["年龄", "姓名"]; // ["自定义001","【姓名】","【年龄】","自定义002"] var waitanalysisstr3 = "自定义001【姓【名】001】自定义002"; var tobeselectedlist3_1 = ["姓【名", "名】001"]; // ["自定义001","【姓【名】","001】自定义002"] var tobeselectedlist3_2 = ["名】001", "姓【名"]; // ["自定义001【姓","【名】001】","自定义002"] var waitanalysisstr4 = "自定义001【【姓名】自定义002"; // 【姓名 、 姓名 交换顺序试试 var tobeselectedlist4_1 = ["【姓名", "姓名"]; // ["自定义001","【【姓名】","自定义002"] var tobeselectedlist4_2 = ["姓名", "【姓名"]; // ["自定义001【","【姓名】","自定义002"] var waitanalysisstr5 = "自定义001【1【姓名】1】自定义002"; // 1【姓名】1 、 姓名 交换顺序试试 var tobeselectedlist5_1 = ["1【姓名】1", "姓名"]; // ["自定义001","【1【姓名】1】","自定义002"] var tobeselectedlist5_2 = ["姓名", "1【姓名】1"]; // ["自定义001【1","【姓名】","1】自定义002"] var waitanalysisstr6 = "自定义001【姓名】】自定义002"; // 姓名 、 姓名】 交换顺序试试 var tobeselectedlist6_1 = ["姓名】", "姓名"]; // ["自定义001","【姓名】】","自定义002"] var tobeselectedlist6_2 = ["姓名", "姓名】"]; // ["自定义001","【姓名】","】自定义002"] var temptargetarr1_1 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr1, tobeselectedlist1_1); console.log(json.stringify(temptargetarr1_1)); var temptargetarr1_2 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr1, tobeselectedlist1_2); console.log(json.stringify(temptargetarr1_2)); var temptargetarr2_1 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr2, tobeselectedlist2_1); console.log(json.stringify(temptargetarr2_1)); var temptargetarr2_2 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr2, tobeselectedlist2_2); console.log(json.stringify(temptargetarr2_2)); var temptargetarr3_1 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr3, tobeselectedlist3_1); console.log(json.stringify(temptargetarr3_1)); var temptargetarr3_2 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr3, tobeselectedlist3_2); console.log(json.stringify(temptargetarr3_2)); var temptargetarr4_1 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr4, tobeselectedlist4_1); console.log(json.stringify(temptargetarr4_1)); var temptargetarr4_2 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr4, tobeselectedlist4_2); console.log(json.stringify(temptargetarr4_2)); var temptargetarr5_1 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr5, tobeselectedlist5_1); console.log(json.stringify(temptargetarr5_1)); var temptargetarr5_2 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr5, tobeselectedlist5_2); console.log(json.stringify(temptargetarr5_2)); var temptargetarr6_1 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr6, tobeselectedlist6_1); console.log(json.stringify(temptargetarr6_1)); var temptargetarr6_2 = gettargetarrbyuserinputandfilterstrs(waitanalysisstr6, tobeselectedlist6_2); console.log(json.stringify(temptargetarr6_2));
其实到现在,都不知道现在的算法是不是包住了所有情况,虽然下面的例子都测试通过了,还是等着真正的测试人员去测试吧!如果哪位大神有更好的方法请赐教,谢谢!
上一篇: Spring 处理请求和响应相关的注解
下一篇: ASP.NET MVC中有四种过滤器类型