Array with children - 以 parent-child 层级的形式显示
Array with children - display it in the form of parent-child hierarchy
我有步骤#1 中显示的数据,我想以 parent 的形式重新排列它,并根据 "id":
step#1:
[
{"id": "card:1.usa", "name": "usa"}, {"id": "card:2", "name": "card2"}, {"id": "card:1", "name": "card1"}, {"id": "card:2.washington", "name": "washington"},
{"id": "card:1.usa.illinios", "name": "illinios"}, {"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
step#2 :
[
{"id": "card:1", "name": "card1", "children": [ {"id": "card:1.usa", "name": "usa", "children":[ {"id": "card:1.usa.illinios", "name": "illinios", "children":[ {"id": "card:1.usa.illinios.city1", "name": "chicago"}] }] } },
{"id": "card:2", "name": "card2", "children": [ {"id": "card:2.washington", "name": "washington" }] }
]
我试图从我这边进行以下操作,但这只能达到第一级 children:
var cardData = [
{"id": "card:1.usa", "name": "usa"}, {"id": "card:2", "name": "card2"}, {"id": "card:1", "name": "card1"}, {"id": "card:2.washington", "name": "washington"},
{"id": "card:1.usa.illinios", "name": "illinios"}, {"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
var subCardList = [];
$scope.parentCard = [];
for(var i=0; i<cardData.length; i++){
if( cardData[i].id.indexOf('.') > -1){
subCardList.push( cardData[i] );
}
}
for(var i=0; i<cardData.length; i++){
for(var j=0; j<subCardList.length; j++){
var cardObj = {};
if( cardData[i].id == subCardList[j].id.substr(0, subCardList[j].id.indexOf('.')) ){ //found matching parent card
cardObj.id = cardData[i].id;
cardObj.children = subCardList[j];
$scope.parentCard.push( cardObj );
}
}
}
请告诉我如何通过 javascript/jquery 实现此目的?
我改进了我的解决方案,使其更加全面,并且还处理了层次结构中的所有卡片都不存在且顺序不同的情况。
子卡数组在处理前根据id排序。这确保卡片的顺序不会破坏此代码。
首先收集所有顶级卡片。然后将每个子卡放入桶中(子集合)。
我提供了额外的数据集 (cardData1) 来突出显示边界条件。
如果您需要更多解释,请告诉我。
var cardData = [{
"id": "card:1.usa",
"name": "usa"
}, {
"id": "card:2",
"name": "card2"
}, {
"id": "card:1",
"name": "card1"
}, {
"id": "card:2.washington",
"name": "washington"
}, {
"id": "card:1.usa.illinios",
"name": "illinios"
}, {
"id": "card:1.usa.illinios.city1",
"name": "chicago"
}]
var cardData1 = [
{
"id": "card:1.usa.illinios.city1.municipality1",
"name": "DumDum"
},{
"id": "card:1.usa",
"name": "usa"
}, {
"id": "card:2",
"name": "card2"
}, {
"id": "card:1",
"name": "card1"
}, {
"id": "card:2.washington",
"name": "washington"
}, {
"id": "card:1.usa.illinios.city1",
"name": "chicago"
},
]
var subCardList = [];
var subCardMap = {};
var parentCardList = [];
var cardMap = {};
for (var i = 0; i < cardData.length; i++) {
if (cardData[i].id.indexOf('.') > -1) {
subCardList.push(cardData[i]);
subCardMap[cardData[i].id] = cardData[i];
} else {
//top level cards
var cardId = cardData[i].id;
var parentCard = {
id: cardId,
name: cardData[i].name,
children: []
};
cardMap[cardId] = parentCard;
parentCardList.push(parentCard);
}
}
//Sort the subcard list to ensure missing hierarchial cards do not break implementation
subCardList.sort(function (a, b) {
return a.id.toLowerCase().localeCompare(b.id.toLowerCase());
});
//Build buckets(children array) for child cards on the fly
for (var j = 0; j < subCardList.length; j++) {
var topCardId = subCardList[j].id.substr(0, subCardList[j].id.indexOf('.'));
placeInBucket(topCardId, subCardList[j]); //find matching parent card from map
}
function placeInBucket(topCardId, childCard) {
var topCard = cardMap[topCardId]; //get top card
var childIds = childCard.id.split(".");
childIds.splice(0, 1); //Remove the top card id
var childId = "";
var bucket = topCard.children; //Assign the initial bucket as the topcard children array
//loop through all the hierarchy and create complete hierarchy
for (var i = 0; i < childIds.length; i++) {
var key = topCardId + childId + "." + childIds[i];
if (!subCardMap[key]) {
childId += "." + childIds[i];
continue;
} //Do not build hierarchy for missing subcards in the id chain
var child = cardMap[key];
if (!child) {
bucket.push(childCard);
cardMap[key] = childCard; //Register new child to cardMap
break;
}
if (!child.children) child.children = []; //Add Children array to a leaf card if not existing
bucket = child.children;
childId += "." + childIds[i]; //Append the id to drill down the hierarchy
}
}
console.log(JSON.stringify(parentCardList));
简短的回答:你需要一个 recursive function,一个调用自身嵌套 children 的函数,直到你找到一个没有 children.
的元素
因此,首先,您找到列表中的所有 parents:
[
{"id": "card:2", "name": "card2"},
{"id": "card:1", "name": "card1"},
]
然后,对于这些 objects 中的每一个,您再次 运行 遍历数组,找到后代。例如,对于 card:1
:
[
{"id": "card:1.usa", "name": "usa"},
{"id": "card:1.usa.illinios", "name": "illinios"},
{"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
这是我们需要递归的地方:您需要再次重复相同的过程,将此数组作为您的输入。所以你会发现 "parents" 是:
[
{"id": "card:1.usa", "name": "usa"}
]
和 children:
[
{"id": "card:1.usa.illinios", "name": "illinios"},
{"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
因为你还有 children,你会再次重复,直到你找不到更多 children。
这个例子可能不够简洁(我不确定如何处理 ID),但它有效:
function nestChildren(list, startIndex){
var parents = [];
// Search list for "parents" --> objects with only one period-separated section
for(var i=0;i<list.length;i++){
var ids = list[i].id.substring(startIndex).split('.'); // Count only sections from parent id
if (ids.length == 1){
parents.push(list[i]);
}
}
for(var i=0;i<parents.length;i++){
var parent = parents[i];
var children = [];
// Search list for "children" --> objects with ids that start with the parent id
for(var j=0;j<list.length;j++){
if (list[j].id.indexOf(parent.id) == 0 && list[j].id != parent.id){
children.push(list[j]);
}
}
if (children.length){
// If there's any children, nest those children too
// Pass the found children as the "list" parameter
// and the parent's id length as the second (to count periods from that index)
parent.children = nestChildren(children, parent.id.length + 1);
}
}
return parents;
}
我有步骤#1 中显示的数据,我想以 parent 的形式重新排列它,并根据 "id":
step#1:
[
{"id": "card:1.usa", "name": "usa"}, {"id": "card:2", "name": "card2"}, {"id": "card:1", "name": "card1"}, {"id": "card:2.washington", "name": "washington"},
{"id": "card:1.usa.illinios", "name": "illinios"}, {"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
step#2 :
[
{"id": "card:1", "name": "card1", "children": [ {"id": "card:1.usa", "name": "usa", "children":[ {"id": "card:1.usa.illinios", "name": "illinios", "children":[ {"id": "card:1.usa.illinios.city1", "name": "chicago"}] }] } },
{"id": "card:2", "name": "card2", "children": [ {"id": "card:2.washington", "name": "washington" }] }
]
我试图从我这边进行以下操作,但这只能达到第一级 children:
var cardData = [
{"id": "card:1.usa", "name": "usa"}, {"id": "card:2", "name": "card2"}, {"id": "card:1", "name": "card1"}, {"id": "card:2.washington", "name": "washington"},
{"id": "card:1.usa.illinios", "name": "illinios"}, {"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
var subCardList = [];
$scope.parentCard = [];
for(var i=0; i<cardData.length; i++){
if( cardData[i].id.indexOf('.') > -1){
subCardList.push( cardData[i] );
}
}
for(var i=0; i<cardData.length; i++){
for(var j=0; j<subCardList.length; j++){
var cardObj = {};
if( cardData[i].id == subCardList[j].id.substr(0, subCardList[j].id.indexOf('.')) ){ //found matching parent card
cardObj.id = cardData[i].id;
cardObj.children = subCardList[j];
$scope.parentCard.push( cardObj );
}
}
}
请告诉我如何通过 javascript/jquery 实现此目的?
我改进了我的解决方案,使其更加全面,并且还处理了层次结构中的所有卡片都不存在且顺序不同的情况。
子卡数组在处理前根据id排序。这确保卡片的顺序不会破坏此代码。
首先收集所有顶级卡片。然后将每个子卡放入桶中(子集合)。
我提供了额外的数据集 (cardData1) 来突出显示边界条件。
如果您需要更多解释,请告诉我。
var cardData = [{
"id": "card:1.usa",
"name": "usa"
}, {
"id": "card:2",
"name": "card2"
}, {
"id": "card:1",
"name": "card1"
}, {
"id": "card:2.washington",
"name": "washington"
}, {
"id": "card:1.usa.illinios",
"name": "illinios"
}, {
"id": "card:1.usa.illinios.city1",
"name": "chicago"
}]
var cardData1 = [
{
"id": "card:1.usa.illinios.city1.municipality1",
"name": "DumDum"
},{
"id": "card:1.usa",
"name": "usa"
}, {
"id": "card:2",
"name": "card2"
}, {
"id": "card:1",
"name": "card1"
}, {
"id": "card:2.washington",
"name": "washington"
}, {
"id": "card:1.usa.illinios.city1",
"name": "chicago"
},
]
var subCardList = [];
var subCardMap = {};
var parentCardList = [];
var cardMap = {};
for (var i = 0; i < cardData.length; i++) {
if (cardData[i].id.indexOf('.') > -1) {
subCardList.push(cardData[i]);
subCardMap[cardData[i].id] = cardData[i];
} else {
//top level cards
var cardId = cardData[i].id;
var parentCard = {
id: cardId,
name: cardData[i].name,
children: []
};
cardMap[cardId] = parentCard;
parentCardList.push(parentCard);
}
}
//Sort the subcard list to ensure missing hierarchial cards do not break implementation
subCardList.sort(function (a, b) {
return a.id.toLowerCase().localeCompare(b.id.toLowerCase());
});
//Build buckets(children array) for child cards on the fly
for (var j = 0; j < subCardList.length; j++) {
var topCardId = subCardList[j].id.substr(0, subCardList[j].id.indexOf('.'));
placeInBucket(topCardId, subCardList[j]); //find matching parent card from map
}
function placeInBucket(topCardId, childCard) {
var topCard = cardMap[topCardId]; //get top card
var childIds = childCard.id.split(".");
childIds.splice(0, 1); //Remove the top card id
var childId = "";
var bucket = topCard.children; //Assign the initial bucket as the topcard children array
//loop through all the hierarchy and create complete hierarchy
for (var i = 0; i < childIds.length; i++) {
var key = topCardId + childId + "." + childIds[i];
if (!subCardMap[key]) {
childId += "." + childIds[i];
continue;
} //Do not build hierarchy for missing subcards in the id chain
var child = cardMap[key];
if (!child) {
bucket.push(childCard);
cardMap[key] = childCard; //Register new child to cardMap
break;
}
if (!child.children) child.children = []; //Add Children array to a leaf card if not existing
bucket = child.children;
childId += "." + childIds[i]; //Append the id to drill down the hierarchy
}
}
console.log(JSON.stringify(parentCardList));
简短的回答:你需要一个 recursive function,一个调用自身嵌套 children 的函数,直到你找到一个没有 children.
的元素因此,首先,您找到列表中的所有 parents:
[
{"id": "card:2", "name": "card2"},
{"id": "card:1", "name": "card1"},
]
然后,对于这些 objects 中的每一个,您再次 运行 遍历数组,找到后代。例如,对于 card:1
:
[
{"id": "card:1.usa", "name": "usa"},
{"id": "card:1.usa.illinios", "name": "illinios"},
{"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
这是我们需要递归的地方:您需要再次重复相同的过程,将此数组作为您的输入。所以你会发现 "parents" 是:
[
{"id": "card:1.usa", "name": "usa"}
]
和 children:
[
{"id": "card:1.usa.illinios", "name": "illinios"},
{"id": "card:1.usa.illinios.city1", "name": "chicago"}
]
因为你还有 children,你会再次重复,直到你找不到更多 children。
这个例子可能不够简洁(我不确定如何处理 ID),但它有效:
function nestChildren(list, startIndex){
var parents = [];
// Search list for "parents" --> objects with only one period-separated section
for(var i=0;i<list.length;i++){
var ids = list[i].id.substring(startIndex).split('.'); // Count only sections from parent id
if (ids.length == 1){
parents.push(list[i]);
}
}
for(var i=0;i<parents.length;i++){
var parent = parents[i];
var children = [];
// Search list for "children" --> objects with ids that start with the parent id
for(var j=0;j<list.length;j++){
if (list[j].id.indexOf(parent.id) == 0 && list[j].id != parent.id){
children.push(list[j]);
}
}
if (children.length){
// If there's any children, nest those children too
// Pass the found children as the "list" parameter
// and the parent's id length as the second (to count periods from that index)
parent.children = nestChildren(children, parent.id.length + 1);
}
}
return parents;
}