2017-08-14 108 views
0

我想創建一個函數,它將遍歷數組的層次並將它們連接在一起。我正在努力想辦法做到這一點。Javascript遞歸函數問題

我調用一個Web API,它返回一些具有相同屬性和佈局的數據,但可以在有多少Hierarchy層數組中有所不同。

文件夾:文件夾可以包含「路線」,但也可以包含在其內部的另一個文件夾,然後可以還含有較多的「路線」等

路線:單個對象,它是一個路由。

例如:

{ 
    "id":1, 
    "folders":[ 
     { 
     "id":2, 
     "folders":[ 
      { 
       "id":3, 
       "folders":[], 
       "routes":[] 
      } 
     ], 
     "routes":[ 
      { 
       "id":1002, 
       "name":"Route3" 
      }, 
      { 
       "id":1003, 
       "name":"Route4" 
      } 
     ] 
     } 
    ], 
    "routes":[ 
     { 
     "id":1000, 
     "name":"Route1" 
     }, 
     { 
     "id":1001, 
     "name":"Route2" 
     } 
    ] 
} 

我需要能夠繼續深入到層次結構和CONCAT所有文件夾數組的路線陣列,這樣我就可以有一個孩子綁定劍道的TreeView這將是文件夾陣列。

到目前爲止,我曾嘗試:

for (var i = 0; i < Folders.length; i++) { 
    if (Folder[i].Folders.length > 0) { 
     for (var e = 0; e < Folder[i].Folder[e].length; e++) { 
      if (Folder[i].Folders[e].length > 0) { 
       ... 
      } 
     } 
    } 
} 

與該方法的問題是,我永遠不會知道有多少層會出現,因此不是一個可行的方法。

結果我需要的是上面的例子看起來像:

{ 
    "id":1, 
    "folders":[ 
     { 
     "id":2, 
     "folders":[ 
      { 
       "id":3, 
       "folders":[ 

       ], 
       "routes":[ 

       ] 
      }, 
      { 
       "id":1002, 
       "name":"Route3" 
      }, 
      { 
       "id":1003, 
       "name":"Route4" 
      } 
     ] 
     }, 
     { 
     "id":1000, 
     "name":"Route1" 
     }, 
     { 
     "id":1001, 
     "name":"Route2" 
     } 
    ] 
} 
+0

你或許應該更新與樣品JSON和所需的輸出你的問題,因此,很容易理解 –

+0

你有沒有嘗試過了嗎?向我們展示您已擁有的代碼,並詢問您遇到麻煩的部分。 – DDRamone

+0

@DDRamone對不起,我添加了我迄今爲止所擁有的內容。 –

回答

1

var flatRoutes = function(folders){ 
 
    for(var i in folders){ 
 

 
    var cur = folders[i]; 
 
    if(cur.hasOwnProperty('folders')){ 
 
     flatRoutes(cur.folders); 
 
    } 
 
    
 
    if(cur.hasOwnProperty('routes')){ 
 
     for(var i in cur.routes){ 
 
     cur.folders.push(cur.routes[i]); 
 
     } 
 
     
 
     delete cur.routes; 
 
    } 
 
    
 
    } 
 
    
 
    return folders; 
 
} 
 
    
 

 
var json = { 
 
    "id":1, 
 
    "folders":[ 
 
     { 
 
     "id":2, 
 
     "folders":[ 
 
      { 
 
       "id":3, 
 
       "folders":[], 
 
       "routes":[] 
 
      } 
 
     ], 
 
     "routes":[ 
 
      { 
 
       "id":1002, 
 
       "name":"Route3" 
 
      }, 
 
      { 
 
       "id":1003, 
 
       "name":"Route4" 
 
      } 
 
     ] 
 
     } 
 
    ], 
 
    "routes":[ 
 
     { 
 
     "id":1000, 
 
     "name":"Route1" 
 
     }, 
 
     { 
 
     "id":1001, 
 
     "name":"Route2" 
 
     } 
 
    ] 
 
} 
 

 

 
var routes = flatRoutes([json]); 
 

 
console.log(routes);

+0

這是當你不知道它有多深時如何使用遞歸函數的例子。希望它會有所幫助 – DDRamone

+0

在您創建的routes數組中,似乎沒有該文件夾(ID = 3的文件夾),它需要包含該路由數組中的所有文件夾。 –

+0

看更新後的答案 – DDRamone

0

從AB object刪除property,你可以利用delete object.property

我採取了以下步驟,我認爲它給出了正確的結果。

  • 創建modular功能 - formatData
  • 檢查folders陣列具有任何數據或不
  • 如果folders陣列有數據顯示,它調用formatData爲每folder
  • 然後,檢查爲routes陣列。如果沒有路由,返回data
  • 如果routes陣列有數據,就按每個route到該文件夾​​陣列和remove來自物體的routes屬性。

let data = { 
 
    "id": 1, 
 
    "folders": [{ 
 
    "id": 2, 
 
    "folders": [{ 
 
     "id": 3, 
 
     "folders": [], 
 
     "routes": [] 
 
    }], 
 
    "routes": [{ 
 
     "id": 1002, 
 
     "name": "Route3" 
 
     }, 
 
     { 
 
     "id": 1003, 
 
     "name": "Route4" 
 
     } 
 
    ] 
 
    }], 
 
    "routes": [{ 
 
     "id": 1000, 
 
     "name": "Route1" 
 
    }, 
 
    { 
 
     "id": 1001, 
 
     "name": "Route2" 
 
    } 
 
    ] 
 
}; 
 

 
function formatData(data) { 
 
    if (data.folders.length) { 
 
    data.folders.forEach(folder => { 
 
     return formatData(folder); 
 
    }); 
 
    } 
 
    if (data.routes.length) { 
 
    data.routes.forEach(route => { 
 
     data.folders.push(route); 
 
    }); 
 
    delete data.routes; 
 
    } 
 
    return data; 
 
} 
 

 
console.log(formatData(data));

0

你可以使用迭代和遞歸方法。

var data = { id: 1, folders: [{ id: 2, folders: [{ id: 3, folders: [], routes: [] }], routes: [{ id: 1002, name: "Route3" }, { id: 1003, name: "Route4" }] }], routes: [{ id: 1000, name: "Route1" }, { id: 1001, name: "Route2" }] }, 
 
    result = [data].map(function iter(o) { 
 
     return { 
 
      id: o.id, 
 
      folders: (o.folders && o.folders.map(iter) || []).concat(o.routes || []) 
 
     }; 
 
    })[0]; 
 

 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }