B4J Question [SOLVED] Treview from list of delimited paths?

tchart

Well-Known Member
Licensed User
Longtime User
I have a list of items like this "root.level1.level2.level3.level4" - Im not able to change the format of the data in the list.

e.g.
root.A.A.A.A
root.A.A.A.B
root.A.A.A.C
root.A.B.A.A
root.A.B.A.B
root.A.C.A.A
root.A.D.A.A
etc

I am displaying this in a treeview in B4J and in order to construct the treeview I am looping through the list and then the "levels" within each item. When going through the levels I have to locate the parent in the treeview and then create the child.

For example if I was creating node root.A.A.A.A I would locate root.A.A.A in the treeview and then create the child.

This worked fine while the dataset was small but now it takes 90 seconds to populate the treeview and will continue to get slower.

Does any one have any example of creating a treveiew from a delimited path like this?
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Hi!
When i face this kind of algorithms i dont usually handle it with nested loops.

What i usually do is do one loop first, that will fill a map with each node and its reference.
Then a second loop will create the nodes and call the parents reference for each node to add it. so i dont have nested nodes.

So just 2 loops.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Hi!
When i face this kind of algorithms i dont usually handle it with nested loops.

What i usually do is do one loop first, that will fill a map with each node and its reference.
Then a second loop will create the nodes and call the parents reference for each node to add it. so i dont have nested nodes.

So just 2 loops.
You're not referring to recursion, are you? ?
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
You're not referring to recursion, are you?
may be is the language that i cant fully wrasp what you refer, for me recursion is the same as a loop. i am saying that op shouldnt use nested recursion that i assume he is using.
 
Upvote 0

tchart

Well-Known Member
Licensed User
Longtime User
Yeah its a bit tricky. I have the code to build the hierarchy but its currently very slow as I am looking up the parent node in the tree via its path which is expensive.
 
Upvote 0

tchart

Well-Known Member
Licensed User
Longtime User
Ok here is a solution that I can work with

The logic is from here; https://stackoverflow.com/questions/45075261/flat-directory-path-to-heirarchy

This returns a hierarchy map which I can use - demo below converts this to JSON to validate the results.

B4X:
Sub AppStart (Args() As String)
    Dim data As List
    data.Initialize
    
    data.Add("root.A.A.A.A")
    data.Add("root.A.A.A.B")
    data.Add("root.A.A.A.C")
    data.Add("root.A.B.A.A")
    data.Add("root.A.B.A.B")
    data.Add("root.A.C.A.A")
    data.Add("root.A.D.A.A")
    
    data.Sort(True)
    
    Dim m As Map = convertToHierarchy(data)
    
    Dim j As JSONGenerator
    j.Initialize(m)
    
    Log(j.ToPrettyString(4))
    
End Sub

Sub convertToHierarchy(data As List) As Map
    Dim rootNode As Map
    rootNode.Initialize
    rootNode.Put("root",CreateMap())

    For Each path As String In data 
        buildNodeRecursive(rootNode, Regex.Split("\.",path), 0)
    Next

    Return rootNode
End Sub

Sub buildNodeRecursive(node As Map, path As List, idx As Int)
    If idx < path.Size Then
        Dim item As String = path.Get(idx)
        If node.ContainsKey(item) = False Then node.Put(item,CreateMap())   
        buildNodeRecursive(node.Get(item), path, idx + 1)   
    End If
End Sub
 
Upvote 0

tchart

Well-Known Member
Licensed User
Longtime User
Heres the code to build the treeview - for my app the time went down from 90s to 86ms.

B4X:
Sub convertToHierarchy(data As List) As Map
    Dim rootNode As Map
    rootNode.Initialize
    rootNode.Put("root",CreateMap())

    For Each path As String In data
        buildNodeRecursive(rootNode, Regex.Split("\.",path), 0)
    Next

    Return rootNode
End Sub

Sub buildNodeRecursive(node As Map, path As List, idx As Int)
    If idx < path.Size Then
        Dim item As String = path.Get(idx)
        If node.ContainsKey(item) = False Then node.Put(item,CreateMap())
        buildNodeRecursive(node.Get(item), path, idx + 1)
    End If
End Sub

Sub PopulateTreeview()
    vwTree.ClearSelection
    vwTree.Root.Children.Clear
    
    Dim data As List
    data.Initialize
    
    Dim Cursor1 As ResultSet
    Cursor1 = DB.ExecQuery("select path from series")
    
    Do While Cursor1.NextRow
        data.Add(Cursor1.GetString2(0))
    Loop
    
    data.Sort(True)
    
    Dim nodes As Map = convertToHierarchy(data)
    
    Dim Parent As TreeItem
    Parent = vwTree.Root
    
    Dim t1 As Long = DateTime.Now
    
    For Each k As String In nodes.Keys
        Dim tti As TreeItem
        tti.Initialize("tti", k)
        Parent.Children.Add(tti)
        BuildTree(nodes.Get(k),tti)   
    Next   
    
    Dim t2 As Long = DateTime.Now
    Dim d As Long = t2-t1
Log("Response time: " & d )
    
Cursor1.Close
End Sub

Sub BuildTree(m As Map, parent As TreeItem)
    For Each k As String In m.Keys
        Dim ti As TreeItem
        ti.Initialize("", k)
        parent.Children.Add(ti)
        BuildTree(m.Get(k), ti)
    Next
End Sub
 
Upvote 0
Top