2013-12-11 26 views
0

我有要求從基於parentId的json數組中找到關係,並在順序結構中插入到數組中。 ParentId映射到父親_Id。Algo找到深度並在JSON數組中順序插入

[{"_Id":1,parentId:"",name:'A'}, 
{"_Id":4,parentId:2,name:'D'}, 
{"_Id":2,parentId:1,name:'B'}, 
{"_Id":5,parentId:3,name:'E'}, 
{"_Id":3,parentId:1,name:'C'}] 

上面的數組需要轉換爲下面的結構與深度字段。

[{"_Id":1,parentId:"",name:'A', 'depth':1}, 
{"_Id":2,parentId:1,name:'B', 'depth':2}, 
{"_Id":4,parentId:2,name:'D', 'depth':3}, 
{"_Id":3,parentId:1,name:'C', 'depth':2}, 
{"_Id":5,parentId:3,name:'E', 'depth':3}] 

1 
    2 
     4 
    3 
     5 

我是一個新手程序員,需要提示。

var finalArray = []; 
var initPath = function (task) { 
    // TODO 
}; 
for (var i = 0, len = array.length; i < len; i++) { 
    if (array[i].parentId == "") { 
     array[i]['depth'] = 1; 
     finalArray(array[i]); 
     initPath(array[i]); 
    } 
} 
+0

它不應該是一個與parentId 3是深度= 4? – ronnyfm

+0

@ronnyfm:不,因爲它的父母在深度爲2. –

+0

這聽起來很可行。你到目前爲止取得了哪些進展? –

回答

1

嗯,我不會爲你做所有的工作,但是這裏有一個解決方案,它不增加深度而重新排列元素的順序。這是on JSFiddle,這裏的相關代碼:

var addDepth = function(data) { 
    var depth = 0, nodes = data.filter(function(item) { 
     return item.parentId == ""; 
    }), total = nodes.length; 

    do { 
     depth++; 
     nodes.forEach(function(node) {node.depth = depth;}); 
     var ids = nodes.map(function(item) {return item["_Id"];}); 
     nodes = data.filter(function(item) { 
      return ids.indexOf(item.parentId) > -1; 
     }); 
     total += nodes.length 
    } while (nodes.length > 0 && total <= data.length); 
    return data; 
}; 

注意這改變了地方的數組,好好嘗試創建一個克隆。這可能或可能不是你想要的。 (正如我最近關注函數式編程一樣,它至少略微冒犯了我自己的敏感性。)這應該是相對容易改變的。

請注意,這實際上是我的第二個版本。 first one在我看來更加優雅。但它是基於the Ramda library我還在開發中。雖然我喜歡圖書館,並發現它易於使用,我不一定會想到這個代碼更加明顯那些誰不這樣做函數式編程的很多:

var addDepth = function(data) { 
    var depth = 0, nodes = filter(pipe(get("parentId"), eq("")), data), 
     total = nodes.length; 
    do { 
     depth++; 
     nodes.forEach(function(node) {node.depth = depth;}); 
     nodes = filter(pipe(get("parentId"), flip(contains)(pluck("_Id", nodes))), data); 
     total += nodes.length 
    } while (nodes.length > 0 && total <= data.length); 
    return data; 
}; 
+0

感謝斯科特真棒解決方案。 – Sumeet

1

那麼,你可以找到足夠簡單的:他們沒有parentId。一旦你有了根,你可以找到所有的深度2節點:父母是根的任何東西。進一步考慮:如果父節點的父節點處於深度n-1(根是一種特殊情況),則節點處於深度n。繼續尋找,直到一切都有了深度。

+0

雖然如果數據不好(循環父結構),你可能會看起來很長時間! :) –

+0

如何使這個數據更有效率的任何建議? – Sumeet

+0

結構沒有什麼特別的錯,當然沒有什麼效率低下的。 (演示文稿,帶有混合引用風格,很奇怪。)但是有一個問題,數據的來源是否可以確保不會有像我在評論中描述的那樣的循環題。如果不能有這樣的循環,這種方法將正常工作。可能會有更高效的方法,但這是一個相當簡單的方法,我會先嚐試。 –

1

以下方法將遞歸遍歷該樹,並在每次向另一個級別下降時將計數值加1。這確實不是最有效的方法,但在我看來這是最簡單的方法。

var array = [{"_Id":1,parentId:"",name:'A'}, 
{"_Id":4,parentId:2,name:'D'}, 
{"_Id":2,parentId:1,name:'B'}, 
{"_Id":5,parentId:3,name:'E'}, 
{"_Id":3,parentId:1,name:'C'}]; 

for(var i=0;i<array.length;i++) { 
    array[i]["depth"] = findDepth(array[i]); 
} 

function findDepth(item) { 
    if(item.parentId==="") 
     return 1; 
    for(var i=0;i<array.length;i++) { 
     if(array[i]._Id===item.parentId) 
      return 1+findDepth(array[i]); 
    } 
} 
+1

這可能可以通過首先製作一個索引對象來提高效率,您可以通過它的_Id屬性查找項目的索引。那麼你不需要做內部循環,這將是相當有效的。但它與我的共享唯一的部分解決方案特性,因爲它不會重新排列元素。 –

+1

這也可能會導致在不良數據場景中出現無限遞歸(parentId在循環中相互追逐)OP說這是不可能的,但是我看到實際發生了很多「不可能」的數據條件! :) –