2015-10-20 44 views
1

我有第1步中顯示的數據,並且我想按照第2步中的步驟#2基於「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" }] } 
] 

我試圖做的從我身邊下面,但這僅僅得到第一級子:

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的實現這一目標?

+0

您應該只適用於您的$範圍在您的視圖中需要什麼。 – gr3g

+0

@ gr3g - 刪除了$ scope變量 – Mustang

+0

@SAM添加了一個修改後的解決方案,處理邊緣案例 – santon

回答

0

我改進了我的解決方案,使其更全面,並且處理層次結構中的所有卡片都不存在並且順序不同的情況。

處理前根據id對子卡陣列進行排序。這可以確保卡的順序不會破壞此代碼。

首先收集所有頂級卡片。然後將每個子卡放入桶(Children collection)中。

我提供了額外的數據集(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); 
 
      \t 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));

+0

我想獲得最終數組結果,如我的問題中步驟#2中指定的那樣。你提供的解決方案並沒有這樣做:-( – Mustang

+0

@SAM我看到了..我錯過了嵌套。 – santon

+0

謝謝你的解決方案。當它與評論一起嵌入時更多地喜歡它! – Mustang

0

答案很簡單:你需要一個recursive function,直到找到一個沒有孩子的元素自稱窩孩子的功能。

所以,首先,你會發現所有的家長列表:

[ 
    {"id": "card:2", "name": "card2"}, 
    {"id": "card:1", "name": "card1"}, 
] 

然後,對於每個對象,您通過數組再次運行,發現後代。例如,對於card:1

[ 
    {"id": "card:1.usa", "name": "usa"}, 
    {"id": "card:1.usa.illinios", "name": "illinios"}, 
    {"id": "card:1.usa.illinios.city1", "name": "chicago"} 
] 

這是我們需要遞歸性:您需要再次重複同樣的過程中,考慮這個數組作爲輸入。因此,「父母」,你會發現是:

[ 
    {"id": "card:1.usa", "name": "usa"} 
] 

而且孩子:

[ 
    {"id": "card:1.usa.illinios", "name": "illinios"}, 
    {"id": "card:1.usa.illinios.city1", "name": "chicago"} 
] 

既然你還有孩子,你要再次重複,直到你不找任何更多的孩子。

這個例子可能不乾淨,因爲它可以(我不知道如何對付IDS),但它的工作原理:

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; 
} 

Working JSFiddle here

+0

失敗,如果一個卡在層次結構鏈被刪除。 {「id」:「card:1.usa.illinios」,「name」:「illinios」}並運行你的小提琴 – santon

+0

@santon是的,它會失敗,我沒有意識到層次結構中的牌可以被刪除,問題沒有任何這樣的情況... –

+0

我同意這個問題沒有,但沒有什麼說等級將存在或關於順序 – santon