2017-08-10 68 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 
}