Какое отличное решение! Это может сделать для удобной маленькой утилиты. Это прекрасно.
Я знаю, что прошло много времени с тех пор, как вы опубликовали это; Я не смог найти оригинал, но нашел копию в архиве здесь .
Я немного изменил его для краткости и перевел на VB.NET для тех, кому это может быть интересно.
Вот конечный результат:
Главная
Module Main
Sub Main()
With New Test
.Render()
End With
Console.WriteLine()
Console.Write("Press any key to exit...")
Console.ReadKey()
End Sub
End Module
Тест
Public Class Test
Private ReadOnly Tree As Tree
Public Sub New()
Me.Tree = New Tree(Me.Text, "-", 1)
End Sub
Public Sub Render()
Me.Render(Me.Tree.Nodes)
End Sub
Public Sub Render(Nodes As List(Of Node))
Nodes.ForEach(Sub(Node As Node)
Console.WriteLine("{0}{1}", Space(Node.Level), Node.Text)
Me.Render(Node.Nodes)
End Sub)
End Sub
Private ReadOnly Property Text As String
Get
Return _
"TEST DATA" & vbCrLf &
"countries" & vbCrLf &
"-france" & vbCrLf &
"--paris" & vbCrLf &
"--bordeaux" & vbCrLf &
"-germany" & vbCrLf &
"--hamburg" & vbCrLf &
"--berlin" & vbCrLf &
"--hannover" & vbCrLf &
"--munich" & vbCrLf &
"-italy" & vbCrLf &
"subjects" & vbCrLf &
"-math" & vbCrLf &
"--algebra" & vbCrLf &
"--calculus" & vbCrLf &
"-science" & vbCrLf &
"--chemistry" & vbCrLf &
"--biology" & vbCrLf &
"other" & vbCrLf &
"-this" & vbCrLf &
"-that"
End Get
End Property
End Class
дерево
Public Class Tree
Private Level As Integer
Public Sub New(Text As String, LevelIndicator As String)
Me.New(Text, LevelIndicator, 0)
End Sub
Public Sub New(Text As String, LevelIndicator As String, StartingIndex As Integer)
Me.Load(Text, LevelIndicator, StartingIndex)
End Sub
Public ReadOnly Property Nodes As List(Of Node)
Get
Return _Nodes
End Get
End Property
Private ReadOnly _Nodes As New List(Of Node)
Private Sub Load(Text As String, LevelIndicator As String, StartingIndex As Integer)
Dim iLevel As Integer
Dim oParents As Stack(Of Node)
Dim oNode As Node
oParents = New Stack(Of Node)
Text.ToLines(StartingIndex).ForEach(Sub(Line As String)
oNode = New Node(Line, LevelIndicator)
If oNode.Level = 0 Then ' Root '
Me.Nodes.Add(oNode)
oParents.Push(oNode)
Me.Level = 0
ElseIf oNode.Level - Me.Level > 1 Then ' Skipped generation(s) '
Throw New FormatException("The outline structure is invalid.")
ElseIf oNode.Level = Me.Level Then ' Sibling '
oParents.Pop()
Me.Level = oParents.SetNode(oNode, Me.Level)
ElseIf oNode.Level - Me.Level = 1 Then ' Child '
Me.Level = oParents.SetNode(oNode, Me.Level + 1)
ElseIf oNode.Level < Me.Level Then ' Walk back up the stack '
For iLevel = 0 To Me.Level - oNode.Level
oParents.Pop()
Next
Me.Level = oParents.SetNode(oNode, oNode.Level)
End If
End Sub)
End Sub
End Class
Node
Public Class Node
Public Sub New(Line As String, LevelIndicator As String)
_Level = Line.PrefixCount(LevelIndicator)
_Text = Line.StripPrefix(LevelIndicator)
End Sub
Public ReadOnly Property Nodes As List(Of Node)
Get
Return _Nodes
End Get
End Property
Private ReadOnly _Nodes As New List(Of Node)
Public ReadOnly Property Level As Integer
Get
Return _Level
End Get
End Property
Private ReadOnly _Level As Integer
Public ReadOnly Property Text As String
Get
Return _Text
End Get
End Property
Private ReadOnly _Text As String
End Class
Расширения
Public Module Extensions
<Extension>
Public Function PrefixCount(Text As String, Prefix As String) As Integer
Dim iIndex As Integer
PrefixCount = 0
Do While Text.StartsWith(Prefix)
iIndex = Text.IndexOf(Prefix)
If iIndex = -1 Then
Exit Do
Else
Text = Text.Substring(iIndex + Prefix.Length)
PrefixCount += 1
End If
Loop
End Function
<Extension>
Public Function StripPrefix(Text As String, Prefix As String) As String
StripPrefix = Text
Do While StripPrefix.StartsWith(Prefix)
StripPrefix = StripPrefix.Substring(Prefix.Length)
Loop
End Function
<Extension>
Public Function ToLines(Text As String, StartingIndex As Integer) As List(Of String)
Return Split(Text, vbCrLf).Where(Function(Line As String)
Return Line.IsNullOrWhiteSpace = False
End Function).Skip(StartingIndex).ToList
End Function
<Extension>
Public Function SetNode(Parents As Stack(Of Node), Node As Node, Level As Integer) As Integer
Parents.Peek.Nodes.Add(Node)
Parents.Push(Node)
Return Level
End Function
<Extension>
Public Function ToFormat(Template As String, ParamArray Values As Object()) As String
Return String.Format(Template, Values)
End Function
End Module