现有一个LIST:
[
{
"type":"呼吸系统",
"illness":"肺气肿",
"quotaName": "血压"
},
{
"type":"呼吸系统",
"illness":"肺气肿",
"quotaName": "血常规"
},
{
"type":"呼吸系统",
"illness":"哮喘",
"quotaName": "血常规"
},
{
"type":"循环系统",
"illness":"高血压",
"quotaName": "心电图"
},
{
"type":"循环系统",
"illness":"高血压",
"quotaName": "心电彩超"
}
]
我想得到的list:
[
{
"type":"呼吸系统",
"illnessList":[
{
"name":"肺气肿",
"quotaList":[
{
"name":"血压"
},
{
"name":"血常规"
}
]
},
{
"name":"哮喘",
"quotaList":[
{
"name":"血常规"
}
]
}
]
},
{
"type":"循环系统",
"illnessList":[
{
"name":"高血压",
"quotaList":[
{
"name":"心电图"
},
{
"name":"心电彩超"
}
]
}
]
}
]
原有的list,所有疾病系统和疾病,以及疾病检测指标都是合在一起的
我想根据类型分类得到一个list,但始终找不到思路
循环,遍历多次以后感觉脑袋糊掉了,请求各位大大给个思路
女神的闺蜜爱上我2017-06-28 09:26:41
按照题主的输入输出要求,从一个JSONArray
转换到另一个JSONArray
...感觉输出的JSONArray无非是按照了两个属性进行了归类,其实结构应该类似于Map<String,Map<String,List<String>>
,所以我的想法就是把输入的JSONArray
要转化为Map<String, Map<String,List<String>>
的结构即可...而看到我刚才说的按照属性归类...那...很显然...噔噔噔!!!...心中自然浮现了Java8的Collectors.groupingBy
...直接无脑groupingBy
就行了嘛
下面是我的小思路和代码:
既然是面向对象,所以我先创建了一个输入的Bo对象FromDataBo
@Getter
@Setter
public class FromDataBo {
private String type;
private String illness;
private String quotaName;
}
接着是按照输出格式创建的输出对象ToDataBo
(带注释的方法先可以不看...只是转化用的,可以先看数据结构)
@Getter
@Setter
public class ToDataBo {
private String type;
private List<ToDataIllnessBo> illnessList;
/**
* map转化为List<ToDataBo>
* @param map
* @return
*/
public static List<ToDataBo> createByMap(Map<String, Map<String, List<String>>> map){
return map.entrySet().stream().map(ToDataBo::of).collect(Collectors.toList());
}
/**
* 一个Map.Entry<String, Map<String, List<String>>>对应转化为一个ToDataBo
* @param entry
* @return
*/
public static ToDataBo of(Map.Entry<String, Map<String, List<String>>> entry){
ToDataBo dataBo = new ToDataBo();
dataBo.setType(entry.getKey());
dataBo.setIllnessList(entry.getValue().entrySet().stream().map(ToDataIllnessBo::of).collect(Collectors.toList()));
return dataBo;
}
@Getter
@Setter
static class ToDataIllnessBo{
private String name;
private List<ToDataQuotaBo> quotaList;
/**
* 一个Map.Entry<String, List<String>>对应转化为一个ToDataIllnessBo
* @param entry
* @return
*/
public static ToDataIllnessBo of(Map.Entry<String, List<String>> entry){
ToDataIllnessBo dataIllnessBo = new ToDataIllnessBo();
dataIllnessBo.setName(entry.getKey());
dataIllnessBo.setQuotaList(entry.getValue().stream().map(ToDataQuotaBo::new).collect(Collectors.toList()));
return dataIllnessBo;
}
}
@Getter
@Setter
@AllArgsConstructor
static class ToDataQuotaBo {
private String name;
}
}
输入输出对象有了,那就可以进行最重要按属性分类,我先把转化为Map<String,Map<String,List<String>>
的代码贴出来...主要就是这个嘛...注释嘛,熟悉lamdba
的估计一眼就看出来...不熟悉再多了解哈吧
Map<String, Map<String, List<String>>> collect = fromDataBos.stream().collect(
// 按照type分类
Collectors.groupingBy(FromDataBo::getType,
// 按照type分类后,同一类的数据再按照illness分类
Collectors.groupingBy(FromDataBo::getIllness,
// 按照type分类,再按照illness分类后,同一类的数据取其中的QuotaName并转化为集合
Collectors.mapping(FromDataBo::getQuotaName, Collectors.toList()))));
最后是完整的测试代码和结果,最后的result
对象就是你需要的输出JSONArray
public class Test1 {
public static void main(String[] args) {
String from = "[\n" +
" {\n" +
" \"type\":\"呼吸系统\",\n" +
" \"illness\":\"肺气肿\",\n" +
" \"quotaName\": \"血压\"\n" +
" },\n" +
" {\n" +
" \"type\":\"呼吸系统\",\n" +
" \"illness\":\"肺气肿\",\n" +
" \"quotaName\": \"血常规\"\n" +
" },\n" +
" {\n" +
" \"type\":\"呼吸系统\",\n" +
" \"illness\":\"哮喘\",\n" +
" \"quotaName\": \"血常规\"\n" +
" },\n" +
" {\n" +
" \"type\":\"循环系统\",\n" +
" \"illness\":\"高血压\",\n" +
" \"quotaName\": \"心电图\"\n" +
" },\n" +
" {\n" +
" \"type\":\"循环系统\",\n" +
" \"illness\":\"高血压\",\n" +
" \"quotaName\": \"心电彩超\"\n" +
" }\n" +
" ]";
// 把输入的JSONArray字符串转化为FromDataBo集合
List<FromDataBo> fromDataBos = JSONArray.parseArray(from, FromDataBo.class);
// 归类
Map<String, Map<String, List<String>>> collect = fromDataBos.stream().collect(
// 按照type分类
Collectors.groupingBy(FromDataBo::getType,
// 按照type分类后,同一类的数据再按照illness分类
Collectors.groupingBy(FromDataBo::getIllness,
// 按照type分类,再按照illness分类后,同一类的数据取其中的QuotaName并转化为集合
Collectors.mapping(FromDataBo::getQuotaName, Collectors.toList()))));
// 归类后的map转化为输出对象ToDataBo集合
List<ToDataBo> toDataBos = ToDataBo.createByMap(collect);
// 我是输出对象,我在这
JSONArray result = JSONArray.parseArray(JSONArray.toJSONString(toDataBos));
System.out.println(result);
}
}
测试结果:
就酱...
滿天的星座2017-06-28 09:26:41
这个不是后端吐出来的吗?没必要你去做处理啊,跟后端说下就好啊。或者你就用他们吐的,实现你的效果就好。
无非你想更省事。直接一个循环处理。
用上面的数组,在循环里做处理 跟你处理成后来的 是一样的。不如前置处理。性能高。下面的是标准的风格。
界面贴出来。
欧阳克2017-06-28 09:26:41
代码地址
http://jsbin.com/roqejoficu/e...
var convertData = function(data){
let result = [];
var level1Obj = {};
var level2Obj = {};
var level3Obj = {};
data.forEach(function (item, index, arr) {
//一层对象
level1Obj[item.type] = {};
level1Obj[item.type]["type"] = item.type;
//2层对象
level2Obj[item.type+item.illness] = {};
level2Obj[item.type+item.illness]["p1"] = item.type;
level2Obj[item.type+item.illness]["type"] = item.illness;
//3层对象
level3Obj[index] = {};
level3Obj[index]["p1"] = item.type;
level3Obj[index]["p2"] = item.illness;
level3Obj[index]["type"] = item.quotaName;
});
for (var level1 in level1Obj) {
var o1 = {};
o1.type = level1Obj[level1].type;
o1.list = [];
result.push(o1);
for (var level2 in level2Obj) {
if (level2Obj[level2].p1 == level1Obj[level1].type) {
var o2 = {};
o2.type = level2Obj[level2].type;
o2.list = [];
o1.list.push(o2);
for (var level3 in level3Obj) {
if (level3Obj[level3].p1 == level1Obj[level1].type && level3Obj[level3].p2 == level2Obj[level2].type) {
var o3 = {};
o3.type = level3Obj[level3].type;
o2.list.push(o3);
}
}
}
}
}
console.log(result);
return result;
},
var result = convertData(data);
写的不好,如有更优的方法,希望交流交流