遍历xml表,获取数据的优化方案
思路各种引擎语言皆可用
案例走egret.wing
案例需求:只是假设,实际这个需求并不合理, 不针对需求合理性,只针对数据获取的优化
需求:现在战士走路,每走一步会有不一样的提示,这个提示是配置在xml表中的,读取并展示
配置表格式
-
<?xml version="1.0" encoding="UTF-8"?> <h5guideConfigs> <h5guideConfig id="1" stageid="101000000011396" step="1" guideType="1" attrType="1" Noclick="[10,12,19,21]" click="[11,20]" limit="[12,13,,23,24,34,31,21,22]" /> <h5guideConfig id="2" stageid="101000000011396" step="2" guideType="1" attrType="1" Noclick="[5,15,16,24]" click="[23,14]" limit="[15,18,28,26,36,35]" /> <h5guideConfig id="3" stageid="101000000011397" step="1" guideType="1" attrType="1" Noclick="[28,29,31]" click="[21,30]" limit="[23,24,34,35,45,41,31,33]" /> <h5guideConfig id="4" stageid="101000000011397" step="2" guideType="1" attrType="1" Noclick="[41,60,69]" click="[50,51]" limit="[55,56,46,47,87,86,66,65]" /> <h5guideConfig id="5" stageid="101000000011397" step="3" guideType="1" attrType="1" Noclick="[54,55]" click="[56,65]" limit="[60,63,83,82,72,70]" /> <h5guideConfig id="6" stageid="101000000011398" step="1" guideType="1" attrType="1" Noclick="[37,38,46]" click="[47,56]" limit="[41,43,73,72,62,61]" /> <h5guideConfig id="7" stageid="101000000011398" step="2" guideType="1" attrType="1" Noclick="[42,50,51,59]" click="[60,61]" limit="[46,47,67,68,78,75,55,56]" /> </h5guideConfigs>
现在就是我点击某个士兵,可以得到这个士兵的stageId,step,guideType,attrType,通过这些条件来得到想要的Noclick,click,limit属性
let stageMessage:egret.XML=egret.XML.parse(RES.getRes("stage_xml"))//stage_xml为该xml文件在default.res.json中的name
//stageMessage就是我们解析xml得到的数据,然后封装到一个全局属性stageMessage中
//关键部分到了,现在stageMessage中存储的是我们xml表中的全部数据json格式,现在我们知道stageId,step,guideType,attrType来得到想要的一条数据
//最笨的方法,每走一步,我们遍历整个数据来得到想要的数据 e为我点击士兵的点击事件传回e
for(let k in stageMessage){
let v=stageMessage[k];
if(e.stageid==v.stageid&&e.step==v.step&&e.guideType==v.guideType&&e.attrtype==v.attrtype){
return v;
}
}
办法很简单很直接,就是在该士兵每走一步,就去遍历整个xml表来获取到想要的数据,但是如果数据量非常庞大呢?每次可能都需要遍历整张表,如果表中有数据500条,走了20步,如果表中恰巧没有这一步的数据,最多会执行50020次计算 也就是1W次if判断,虽然程序执行次数很快,但是如果表中数据有成千上万条呢?所有有了一次简单的优化:
就是在出现每个士兵时,先根据这个士兵的stageid,将这个士兵的所有步数数据都存起来,存到一个小的列表中,在该士兵走的时候,去遍历这个小表,而不是遍历整个表,在该案例中就是先将stageid相同的存在同一个列表中,计算时候再去遍历整个小表,计算量就可缩短一个量级,如果该stageid只有两条,就最大计算量就是1+202=41次 由1W次变成41次!
先别着急,还有更恐怖的优化方案,思路就是new 一个对象,将stageID相同的数据存在一个对象中,整个对象的属性分别有step,guideType,attrType,Noclick,click,limit
let stageClass=new stageClass();
for(let k in stageMessage){
let v=stageMessage[k];
if(e.stageid==v.stageid){
stageClass.step.v.step=v.step;
stageClass.guideType.v.guideType=v.guideType;
stageClass.attrType.v.attrType=v.attrType;
stageClass.Noclick.v.Noclick=v.Noclick;
stageClass.click.v.click=v.click;
stageClass.limit.v.limit=v.limit;
}
}
第一次简单的优化我们是将一个大的xml解析出来的数据串变成了一个小的数据串,而这次我们直接是将这个小的数据串变成了一个对象,需要的信息放置在对象的各个属性中。step,guideType都是一个个的数组,我们在判断时候完全不需要去遍历,而是直接去找到数组中的条。
假如我们该士兵现在走到第2步,guideType是1,attrType是1;我们需要判断可以直接去;
if(stageClass.step[1]){//是否该步数存在, 不是去遍历数据 而是直接去我已经存好的数据中判断是否存在
return stageClass.Noclick[1];
}
这次只有开头new对象放置属性时需要遍历一遍 也就是20条计算 更加精简!