Jump to content

How to sort data with an unlimited hierarchy?


amonkey
 Share

Recommended Posts

The below code will sort the provided data into a hierarchy… Only 4 levels deep. What logic would I need to use to sort data an unlimited number of levels.

#include <Array.au3>
Local $array[10][03] = [["01", "Cat01", "0"],["02", "Cat02", "01"],["03", "Cat03", "0"],["04", "Cat04", "03"],["05", "Cat05", "01"],["06", "Cat06", "05"],["07", "Cat07", "01"],["08", "Cat08", "06"],["09", "Cat09", "04"],["010", "Cat010", "08"]]
Local $icount
Local $arraysort[1]
For $a = 0 To UBound($array) - 1
If $array[$a][2] = '0' Then
$icount += 1
_ArrayInsert($arraysort, $icount, $array[$a][1])
$array[$a][2] = ""
For $b = 0 To UBound($array) - 1
If $array[$b][2] = $array[$a][0] Then
$icount += 1
_ArrayInsert($arraysort, $icount, "- " & $array[$b][1])
$array[$b][2] = ""
For $c = 1 To UBound($array) - 1
     If $array[$c][2] = $array[$b][0] Then
     $icount += 1
     _ArrayInsert($arraysort, $icount, "- - " & $array[$c][1])
     $array[$c][2] = ""
     For $d = 1 To UBound($array) - 1
     If $array[$d][2] = $array[$c][0] Then
     $icount += 1
     _ArrayInsert($arraysort, $icount, "- - - " & $array[$d][1])
     $array[$d][2] = ""
     For $e = 1 To UBound($array) - 1
         If $array[$e][2] = $array[$d][0] Then
         $icount += 1
         _ArrayInsert($arraysort, $icount, "- - - - " & $array[$e][1])
         $array[$e][2] = ""
         EndIf
     Next
     EndIf
     Next
     EndIf
Next
EndIf
Next
EndIf
Next
_ArrayDisplay($arraysort, "$arraysort")
Edited by amonkey
Link to comment
Share on other sites

  • Moderators

amonkey,

Welcome to the AutoIt forum. :)

And a complicated little question to start with. :wacko:

A few questions:

- I take it the third element of each section is the parent under which the element should be placed?

- Do you want the array format you have now for the output - i.e. with simple dashes to indicate the level?

- How do you generate the intial array? There might be scope to do something there to simplify the problem when it comes to the later sorting.

I wil take a look now but some early answers might prevent a lot of nugatory work. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • Moderators

amonkey,

That was easier than I thought it would be. Here is a script to order your array as you wish - it should work on unlimited levels:

#include <Array.au3>

Global $aArray[10][3] = [["01", "Cat01", "0"], ["02", "Cat02", "01"], ["03", "Cat03", "0"], ["04", "Cat04", "03"], ["05", "Cat05", "01"], _
                         ["06", "Cat06", "05"], ["07", "Cat07", "01"], ["08", "Cat08", "06"], ["09", "Cat09", "04"], ["010", "Cat010", "08"]]

;Create an array to hold the sorted data - we already know the size
Global $iCount = UBound($aArray)
Global $aSorted_Array[$iCount]

; Now we start a function to run through the array - initially looking for base level entries which will be at level 0
_Find_Level("0", 0, $aSorted_Array)

; And this is what we get when we return
_ArrayDisplay($aSorted_Array)

Func _Find_Level($sParent, $iLevel, ByRef $aSorted_Array)

    ; This is the index of the array we will load next
    Static $iLoad_Index = 0

    ; Look for entries that have this parent
    For $i = 0 To $iCount - 1
        If $aArray[$i][2] = $sParent Then
            ; Found an entry with the correct parent
            ; Add the required number of "-"
            $sItem = $aArray[$i][1]
            For $j = 1 To $iLevel
                $sItem = "-" & $sItem
            Next
            ; And load int into the array - increasing the load index
            $aSorted_Array[$iLoad_Index] = $sItem
            $iLoad_Index += 1
            ; Now run the function again look for any items that have this item as parent
            _Find_Level($aArray[$i][0], $iLevel + 1, $aSorted_Array)
        EndIf
    Next

EndFunc   ;==>_Find_Level

As czardas mentioned above the function is used recursively - if you are not used to doing this, may I recommend reading the Recursion tutorial in the Wiki to find out more. :)

You will also notice that I sized the array before we started. Changing the size of an array (which is what you were doing with _ArrayInsert) uses ReDim which is amazingly slow. So avoiding that function should be done at all costs. You will see that I just kept track of where the next entry should be inserted. ;)

Please ask if you have any questions. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thank you for this. Implemented and working flawlessly. It is much appreciated!

I did not know about recursive functions. After reading the wiki, I believe I have a grasp around how they operate.

Also, thank you for the information about ReDim being slow.

Link to comment
Share on other sites

  • Moderators

amonkey,

Delighted that I could help and that the script works so well. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...