今天在stackoverflow上面看到的一个问题,我就自己做了做~由于stackoverflow不提倡直接给代码,只提倡给思路,我的英语又烂,表达不清楚,所以我就写在这里,以供以后学习使用。
原题:
I have a Json Structure like below
[ { "category_id": "C1", "category_name": "C1_Name", "item_id": "C1_I1", "item_name": "C1_I1_Name", "variant_id": "C1_I1_V1", "variant_name": "C1_I1_V1_ Name" }, { "category_id": "C1", "category_name": "C1_Name", "item_id": "C1_I1", "item_name": "C1_I1_Name", "variant_id": "C1_I1_V2", "variant_name": "C1_I1_V2_ Name" }, { "category_id": "C1", "category_name": "C1_Name", "item_id": "C1_I2", "item_name": "C1_I2_Name", "variant_id": "C1_I2_V1", "variant_name": "C1_I2_V1_ Name" }, { "category_id": "C1", "category_name": "C1_Name", "item_id": "C1_I2", "item_name": "C1_I2_Name", "variant_id": "C1_I2_V2", "variant_name": "C1_I2_V2_ Name" }, { "category_id": "C2", "category_name": "C2_Name", "item_id": "C2_I1", "item_name": "C2_I1_Name", "variant_id": "C2_I1_V1", "variant_name": "C2_I1_V1_ Name" } ]
I would Like to Group the Json to N' level in javascript , Say by passing the list of keys (say by giving category_id,item_id,variant_id , am expecting the following response)
[ { "category_id": "C1", "category_name": "C1_Name", "item": [ { "item_id": "C1_I1", "item_name": "C1_I1_Name", "variant": [ { "variant_id": "C1_I1_V1", "variant_name": "C1_I1_V1_ Name" }, { "variant_id": "C1_I1_V2", "variant_name": "C1_I1_V2_ Name" } ] }, { "item_id": "C1_I2", "item_name": "C1_I2_Name", "variant": [ { "variant_id": "C1_I2_V1", "variant_name": "C1_I2_V1_ Name" }, { "variant_id": "C1_I2_V2", "variant_name": "C1_I2_V2_ Name" } ] } ] } ]
上答案:
原理很简单,就是先按照给定的key进行分组,然后对每组在查看有没有相同value的key,如果有的话,列出来。然后循环整理。
var json = [
{
"category_id": "C1",
"category_name": "C1_Name",
"item_id": "C1_I1",
"item_name": "C1_I1_Name",
"variant_id": "C1_I1_V1",
"variant_name": "C1_I1_V1_ Name"
},
{
"category_id": "C1",
"category_name": "C1_Name",
"item_id": "C1_I1",
"item_name": "C1_I1_Name",
"variant_id": "C1_I1_V2",
"variant_name": "C1_I1_V2_ Name"
},
{
"category_id": "C1",
"category_name": "C1_Name",
"item_id": "C1_I2",
"item_name": "C1_I2_Name",
"variant_id": "C1_I2_V1",
"variant_name": "C1_I2_V1_ Name"
},
{
"category_id": "C1",
"category_name": "C1_Name",
"item_id": "C1_I2",
"item_name": "C1_I2_Name",
"variant_id": "C1_I2_V2",
"variant_name": "C1_I2_V2_ Name"
},
{
"category_id": "C2",
"category_name": "C2_Name",
"item_id": "C2_I1",
"item_name": "C2_I1_Name",
"variant_id": "C2_I1_V1",
"variant_name": "C2_I1_V1_ Name"
}
];
Array.prototype.remove = function(item) {
var index = this.indexOf(item);
if(index != -1)
this.splice(this.indexOf(item), 1);
return this;
}
function findSameValue(array) {
if(array.length <= 1) return array;
// list all the keys
var keys = [];
var resultKeys = [];
for(var key in array[0]) {
keys.push(key);
resultKeys.push(key);
}
// get the keys with same value
keys.forEach(function(key, index){
var current = array[0][key];
array.forEach(function(value, index){
if(index == 0) return true;
if(value[key] != current) {
resultKeys.remove(key);
return false;
}
});
});
return resultKeys;
}
function recursive(array, groupKeys, index){
if(groupKeys.length == index) return array;
// get the current key
var groupKey = groupKeys[index];
// group the array by key
var map = {};
var size = 0;
array.forEach(function(obj){
var value = obj[groupKey];
if(!map[value]) {
map[value] = [];
size ++ ;
}
map[value].push(obj);
});
// if all the objects in the array have different value, then do not need to group it
if(size == array.length) {
return array;
}
var result = [];
for(var key in map) {
var value = map[key];
if(value.length == 1) {
// if only on element, do not need further group
result.push(value[0]);
} else {
var obj = {};
obj[groupKey] = key;
// list other keys with same value
var keys = findSameValue(value);
// get rid of the keys in the props
keys = keys.filter(function(key){
return groupKeys.indexOf(key) == -1;
});
// insert the key and value
keys.forEach(function(key){
if(key != groupKey) {
obj[key] = value[0][key];
}
});
// delete the keys in the objects
value = value.map(function(v){
keys.forEach(function(key){
delete v[key];
});
return v;
});
// recursively group the array
obj["items"] = recursive(value, groupKeys, index + 1);
result.push(obj);
}
}
return result;
};
console.log(recursive(json, ["category_id", "item_id", "variant_id" ], 0));