需求:把数据按照某个字段分组,然后显示在页面。
话不多说直接上最终截图,本例是按照钻孔编号分组(数据转换流程:需要把表格数据(图1),经过程序转换成json字符串上传至MongoDB,然后通过Groovy把MongoDB数据显示在前端页面,最终生成PDF(图2、图3))。
图1原表格数据
图2最终结果1
图3最终结果2
实现过程:
- 首当其冲想到的是多维数组,通过遍历整个数据,把编号相同的数据放在一个数组,做为一个多维数组的值,然后在依次遍历展示。感觉这样工作量太大,有没有更简便的方法,于是想到了排序。
- 在网上各种经典的排序都大概看了一眼,从众多的排序中看到了一个插入排序,他可以把相同的元素放在前面已排序的元素后面,瞬间感觉这个排序靠谱,但是结合当前实际需求来看,还差点意思,因为这个钻孔编号有可能不是数字,会是字符串,字符串的话,就让人头大了,还要处理,比较复杂。
- 在查询Groovy插入排序的时候,突然看到了分组,于是乎就搜了一下分组,果然强大,一个方法解决上面所有问题。下面详细说一下:
Groovy中的分组可以通过groupBy方法来实现(这不是把MySql的方法拿来用了吗,哈哈),该方法可以根据指定的条件将集合中的元素进行分组。
基本语法:
def groupByMap = list.groupBy { it.property }
list是要进行分组的集合,it.property是根据那个属性来进行分组。groupBy方法会返回一个Map,其中键是根据指定属性分组的值,值是符合该分组条件的元素列表。
- 下面就开始把理论应用于实践,毕竟实践才能检验真理。
图4数据存储(index 22对应的数据就是表格中序号为22的那条数据内容)
1.首先需要一个集合
if(testDataModel3!=null)
{
// testDataModel3是一条查询语句,testDataModel3.ExperimentalData是该语句下的数据,赋值给list
list=testDataModel3.ExperimentalData;
list.sort{a,b-> return (a.get("date")).compareTo(b.get("date"))}
for(int j=0;j<list.size();j++)
{
for(int i=0;i<list.get(j).get("info").size();i++)
{
sortList.add(list.get(j).get("info")[i])
}
}
}
2.集合有了,那我们直接groupBy
/*按钻孔编号进行分组*/
sortList = sortList.groupBy { it.holeNo }
//分组后打印了一下分组的结果
println(sortList)
NICE,这个新的Map键就是根据钻孔编号属性分组的值(就是画红色下划线的这些),而键对应的值就是符合该分组条件的元素列表(蓝色或者黄色下划线的这些)。
3.有了这个Map我们就可以遍历然后展示在页面
/*对排序后的数据进行遍历*/
sortList.each()
{
//每一个编号一页
curPage++
for(int i=0;i<sortList.get(it.key).size();i++)
{
// itemValues为最终要返回的值
itemValues.put(curPage+"_检测日期传值",sortList.get(it.key)[0].checkDate)
itemValues.put(curPage+"_钻孔编号",sortList.get(it.key)[i].holeNo)
itemValues.put(curPage+"_钻孔标高",sortList.get(it.key)[i].holeHeight)
itemValues.put(curPage+"_探杆总长_"+(i+1),sortList.get(it.key)[i].rodLength)
itemValues.put(curPage+"_试验深度_"+(i+1),sortList.get(it.key)[i].testDepth)
itemValues.put(curPage+"_贯入度_"+(i+1),sortList.get(it.key)[i].penetration)
itemValues.put(curPage+"_锤击数_"+(i+1),sortList.get(it.key)[i].hammeringNum)
itemValues.put(curPage+"_锤击速率_"+(i+1),sortList.get(it.key)[i].hammeringRate)
itemValues.put(curPage+"_土层定名_"+(i+1),sortList.get(it.key)[i].soilLayerName)
itemValues.put(curPage+"_备注_"+(i+1),sortList.get(it.key)[i].remark)
}
}