2017-08-10 66 views
0

編輯:我意識到它看起來像我馬上回答的答案。我試圖自己去做,但我開始相信有一個我不完全理解的機制。我無法圍繞這個問題纏住我的頭!Unblattening list to sub-objects

edit2:我誤用了詞!對於「父母」和「孩子」,我不使用「DOM」的含義!這是用於我目前的開發

<body> 
    <h1>FIRST LEVEL TITLE</h1> 
    <h4>test</h4> 
    <h2>SECOND LEVEL TITLE</h2> 
    <h3>THIRD LEVEL TITLE</h3> 
    <h4>test</h4> 
    <h3>THIRD LEVEL TITLE</h3> 
    <h3>THIRD LEVEL TITLE</h3> 
    <h2>SECOND LEVEL TITLE</h2> 
    <h3>THIRD LEVEL TITLE</h3> 
    <h3>THIRD LEVEL TITLE</h3> 
    <h4>test</h4> 
    <h4>test</h4> 
</body> 

「父」與「子」層次結構我要創建的HTML是純虛擬(只存在我的圖書館裏,而不是在HTML)!我的標題標籤嵌套


使用Bridge.NET和Bridge.JQuery我已經成功地檢索標題標籤的完整列表從HTML(H1,H2和等),並將它們存儲到一個平面列表。 現在我試圖給這個列表一個層次結構,因此我列表中的每個元素都有一個屬性「Children」,其中包含所有直接在它們下面的元素,這些子元素包含其他子元素...

元素是一個直接的孩子,如果它與其預期的父母之間沒有中間層次的元素。

列表 H2,H3,H4

H4,H3是,這是H2的孩子的孩子。 但在列表 H2,H4,H3,

H3和H4是H2的孩子

例如:

H1 - FIRST LEVEL TITLE 
H4 - test 
H2 - SECOND LEVEL TITLE 
H3 - THIRD LEVEL TITLE 
H4 - test 
H3 - THIRD LEVEL TITLE 
H3 - THIRD LEVEL TITLE 
H2 - SECOND LEVEL TITLE 
H3 - THIRD LEVEL TITLE 
H3 - THIRD LEVEL TITLE 
H4 - test 
H4 - test 

成爲

H1 - FIRST LEVEL TITLE 
--->H4 - test 
--->H2 - SECOND LEVEL TITLE 
--->--->H3 - THIRD LEVEL TITLE 
--->--->H4 - test 
--->--->--->H3 - THIRD LEVEL TITLE 
--->--->--->H3 - THIRD LEVEL TITLE 
--->H2 - SECOND LEVEL TITLE 
--->--->H3 - THIRD LEVEL TITLE 
--->--->H3 - THIRD LEVEL TITLE 
--->--->H4 - test 
--->--->H4 - test 
中的每個標題的

清單定義如下(可以進行任何修改以幫助實現我想要的)

internal class Title 
{ 
    public TitleLevel Level { get; set; } 
    public string Value { get; set; } 
    public IEnumerable<Title> Children { get; set; } 

    /* removed irrelevant code */ 
} 

internal enum TitleLevel 
{ 
    H6, 
    H5, 
    H4, 
    H3, 
    H2, 
    H1, 
    DummyValue // exists for technical reasons, I may ask for advice on that later 
} 
+1

你如何確定一個H4是H1的直接孩子,而不是H2 – Marco

+0

的直接孩子如果已經把這份名單弄平了,沒有辦法從扁平化之前得到原始信息。你必須將這些信息*包含在平面列表中。說完了,我不清楚你爲什麼要把這個清單弄平。 – HimBromBeere

+0

@Marco編輯我的問題,在代碼之前檢查新文本 – Wndrr

回答

0

因此,這裏是我的解決方案,我想要的東西(未壓扁的列表)

的代碼確實是不漂亮,但它的作品。

它被稱爲像這樣

var hierarchyList = GetTitleHierarchy(flatList); 

這裏是定義

/// <summary> 
/// Turns a flat list of titles into a list where each element contains a list of it children, themselves containing a list of childre, ... 
/// </summary> 
/// <param name="titles">A flat list of titles</param> 
/// <returns>A "cascading" list of titles</returns> 
internal List<Title> GetTitleHierarchy(List<Title> titles) 
{ 
    return PutInParent(titles); 
} 

private List<Title> PutInParent(List<Title> titles) 
{ 
    var output = new List<Title>(); 

    for (int i = 0; i < titles.Count; i++) 
    { 
     // Copy because if passed by reference we'll get loop-referencing 
     var title = titles.Get(i).Copy(); 

     var childrenCount = CountChildren(titles, i); 
     if (childrenCount > 0) 
     { 
      var subItems = titles.GetRange(i + 1, childrenCount); 
      title.Children = PutInParent(subItems); 
     } 

     output.Add(title); 
     i += childrenCount; 
    } 

    return output; 
} 

/// <summary> 
/// Returns the number of titles after the current index that should be children of the current element 
/// </summary> 
/// <param name="titles">the flat list of elements</param> 
/// <param name="startIndex">the current position in the list</param> 
/// <returns></returns> 
internal int CountChildren(List<Title> titles, int startIndex) 
{ 
    var clidrenCount = 0; 

    foreach (var title in titles.Skip(startIndex + 1)) 
    { 
     if (title.IsLevelLowerThan(titles.Get(startIndex).Level)) 
      break; 

     clidrenCount++; 
    } 

    return clidrenCount; 
} 

internal class Title 
{ 
    public TitleLevel Level { get; set; } 
    public string Value { get; set; } 
    public IEnumerable<Title> Children { get; set; } 

    #region Overrides of Object 

    public override string ToString() 
    { 
     return $"{Level} - {Value}"; 
    } 

    #endregion 

    public Title Copy() 
    { 
     return new Title 
     { 
      Level = Level, 
      Value = Value, 
      Children = Children.Select(c => c.Copy()) 
     }; 
    } 

    public bool IsLevelLowerThan(TitleLevel targetLevel) 
    { 
     return (int) Level <= (int) targetLevel; 
    } 
} 

internal enum TitleLevel 
{ 
    H1 = 1, 
    H2 = 2, 
    H3 = 3, 
    H4 = 4, 
    H5 = 5, 
    H6 = 6, 
    DummyValue = 0 
}