Search code examples
.netvb.nettreeview

Group list of the same file revisions and make relationship of them


I try to group those of file revision which have the same root and make relationship between them

For example:

1.17
1.17.1.1
1.17.1.2
1.17.1.2.1.1
1.17.2.1
1.17.2.2
1.18
1.19

Now I would like to group

1.17, 1.18, 1.19 as the same group and make relationship is parent 1
1.17.1.1, 1.17.1.2 as the same group and make relationship is child 1.1
1.17.2.1, 1.17.2.2 as the same group and make relationship is child 1.2
1.17.1.2.1.1 as the same group and make relationship is grandchild 1.1.1

My idea is loop through the list and try to find number of digit by split by dot then compare it with those of list but it's seem to bad

I don't know is there any best way in VB.NET to achieve it?

The output maybe a datatable, with each data row index revision relationship 1 1.17, 1.18, 1.19 1 2 1.17.1.1, 1.17.1.2 1.1 3 1.17.2.1, 1.17.2.2 1.2 4 1.17.1.2.1.1 1.1.1

The relationship between them 1.17, 1.18, 1.19 (maybe have 1.20, 1.21...) are grouped as a root group 1.17.1.1, 1.17.1.2 (maybe have 1.17.1.3, 1.17.1.4...) are grouped as first child group of root group 1.17.2.1, 1.17.2.2 (maybe have 1.17.2.3, 1.17.2.4...) are grouped as second child group of root group 1.17.1.2.1.1 which have the same path with first child group (1.17.1.1.x.y) are grouped as a first grand child group of first child group

I really appreciate for any help and thanks so much for it.


Solution

  • If you want to create a DataTable from the same list of revisions, then you can achieve that using the same idea with some changes for the grouping/relation issue.

    Private Function ToDataTable(revs As IEnumerable(Of String)) As DataTable
        Dim dt As New DataTable
    
        dt.Columns.Add("Id", GetType(Integer)).AutoIncrement = True
        dt.Columns.Add("ParentId", GetType(Integer))
        dt.Columns.Add("Text", GetType(String))
        dt.Columns.Add("Path", GetType(String))
        dt.Columns.Add("ParentPath", GetType(String))
        dt.Columns.Add("Level", GetType(Integer))
    
        For Each rev In revs.OrderBy(Function(x) x)
            Dim arr = Regex.Matches(rev, "\d+\.\d+").
                Cast(Of Match).Select(Function(x) x.Value).ToArray()
            Dim r = dt.NewRow
            Dim parentPath = String.Join(".", arr, 0, arr.Count() - 1)
    
            r.SetField("ParentId", dt.Rows.Cast(Of DataRow).
                FirstOrDefault(Function(x) x.Field(Of String)("Path") = parentPath)?.
                Field(Of Integer)("Id"))
            r.SetField("Text", rev)
            r.SetField("Path", rev)
            r.SetField("ParentPath", parentPath)
            r.SetField("Level", arr.Count)
    
            dt.Rows.Add(r)
        Next
    
        Return dt
    End Function
    

    Also you can create a DataTable from the populated TreeView in the last answer:

    Private Iterator Function GetAllNodes(nodes As TreeNodeCollection) _
        As IEnumerable(Of TreeNode)
        For Each tn In nodes.Cast(Of TreeNode)
            Yield tn
            For Each cn In GetAllNodes(tn.Nodes)
                Yield cn
            Next
        Next
    End Function
    
    Private Function ToDataTable(tv As TreeView) As DataTable
        Dim dt As New DataTable
    
        dt.Columns.Add("Id", GetType(Integer)).AutoIncrement = True
        dt.Columns.Add("ParentId", GetType(Integer))
        dt.Columns.Add("Text", GetType(String))
        dt.Columns.Add("Path", GetType(String))
        dt.Columns.Add("ParentPath", GetType(String))
        dt.Columns.Add("Level", GetType(Integer))
    
        For Each node In GetAllNodes(tv.Nodes)
            Dim r = dt.NewRow
            Dim parentPath = node.Parent?.Text
    
            r.SetField("ParentId", dt.Rows.Cast(Of DataRow).
                        FirstOrDefault(Function(x) x.Field(Of String)("Path") = parentPath)?.
                        Field(Of Integer)("Id"))
            r.SetField("Text", node.Text)
            r.SetField("Path", node.Text)
            r.SetField("ParentPath", parentPath)
            r.SetField("Level", node.Level + 1)
    
            dt.Rows.Add(r)
        Next
    
        Return dt
    End Function
    

    Note here, the node's Level property returns the branch level/group/relation of each node.