2014-07-18 17 views
1

我想建立一個基於數據集DataRelations DataTable的列表,其中返回的表只包括他們之間的關係,知道每個鏈的末端。這樣我的DataSet有7個表。的關係是這樣的:F#導航對象圖返回特定節點

Table1 -> Table2 -> Table3 -> Table4 -> Table5 
          -> Table6 -> Table7 

因此,考慮表1和表7,我想回到表1,2,3,6,7

到目前爲止我的代碼遍歷所有關係,並返回所有表,以便在這個例子中它也返回Table4和Table5。我第一次也是最後一次作爲論點,並且知道我還沒有使用最後一個,但我仍然在試着去思考如何去做,並且是我需要幫助的地方。

type DataItem = 
    | T of DataTable 
    | R of DataRelation list 

let GetRelatedTables (first, last) = 
    let rec flat_rec dt acc = 
     match dt with 
     | T(dt) -> 
      let rels = [ for r in dt.ParentRelations do yield r ] 
      dt :: flat_rec(R(rels)) acc    
     | R(h::t) -> 
      flat_rec(R(t)) acc @ flat_rec(T(h.ParentTable)) acc 
     | R([]) -> [] 
    flat_rec first [] 

回答

1

我覺得像這樣的事情會做到這一點(雖然我沒有測試過)。它返回DataTable list option,理論上,兩個表之間的路徑可能不存在。

let findPathBetweenTables (table1 : DataTable) (table2 : DataTable) = 
    let visited = System.Collections.Generic.HashSet() //check for circular references 
    let rec search path = 
     let table = List.head path 
     if not (visited.Add(table)) then None 
     elif table = table2 then Some(List.rev path) 
     else 
      table.ChildRelations 
      |> Seq.cast<DataRelation> 
      |> Seq.tryPick (fun rel -> search (rel.ChildTable::path)) 
    search [table1] 
+0

好的。這就像一個魅力!儘管遍歷是以另一種方式進行的,但如果結果是相同的,我認爲這不是問題。我會嘗試一些更多的場景來測試它,比如自我參考表或者類似的東西,但是很棒。非常感謝! – Calvin

+0

不客氣。如果您願意,您可以輕鬆地將其更改爲其他方式。它應該很好地處理自引用表。 – Daniel

+0

順便說一句,認爲可能值得指出這只是[DFS]的一個特例(http://en.wikipedia.org/wiki/Depth-first_search)。 [BFS](http://en.wikipedia.org/wiki/Breadth-first_search)對於這個問題可能更有效,但DFS稍微容易實現。 – Daniel