Jump to content
Renderer

AutoIT nested dictionary - print using recursion

Recommended Posts

Hi Guys! I have a small problem regarding nested dictionaries in AutoIT and recursion. Let's consider the following nested dictionary:

 

dictionary = {
    "Key1": "Value1",
    "Key2": {
        "Sub-Key", "Sub-Item",
        "Sub-Key-2": {
            "Sub-Sub-Key": "Sub-Sub-Item"
        }
    }
}

Translated into AutoIT code it would be:

$dict = ObjCreate("Scripting.Dictionary")
$dict.Add("Key1", "Value1")
$dict.Add("Key2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Add("Sub-Key", "Sub-Item")
$dict.Item("Key2").Add("Sub-Key-2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Item("Sub-Key-2").Add("Sub-Sub-Key", "Sub-Sub-Item")

I am trying to print this dictionary to console using recursion. I do not know how to apply it correctly. Here's an example:

func KeyHasSubKeys($dict, $key)
    return (Ubound($dict.Item($key).Items) > 0)
endfunc ;Check Key for Subkeys

func PrintDict($dict)
    for $key in $dict
        if not KeyHasSubKeys($dict, $key) then
            ConsoleWrite($key & ":" $dict.Item($key) & @crlf)
         else 
            for $SubKey in $dict.Item($key)
                ; ... this is were I get stuck
            next
        endif
        
endfunc

Can anyone help me solve this problem? The final output in console shoult be like the nested dictionary I posted above in plaintext. I think this problem can be solved using recursion, becuase it's about finding out if a key has subkeys ans so one. I am new to recursion in programming, so I cannot apply it correctly. 

Thanks in advance!

Share this post


Link to post
Share on other sites

?

$dict = ObjCreate("Scripting.Dictionary")
$dict.Add("Key1", "Value1")
$dict.Add("Key2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Add("Sub-Key", "Sub-Item")
$dict.Item("Key2").Add("Sub-Key-2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Item("Sub-Key-2").Add("Sub-Sub-Key1", "Sub-Sub-Item1")
$dict.Item("Key2").Item("Sub-Key-2").Add("Sub-Sub-Key2", "Sub-Sub-Item2")
$dict.Add("Key3", "Value3")


PrintDict($dict)

func KeyHasSubKeys($dict, $key)
    return IsObj($dict.Item($key))
endfunc ;Check Key for Subkeys

func PrintDict($dict)
    for $key in $dict
        if not KeyHasSubKeys($dict, $key) then
            ConsoleWrite($key & ":" & $dict.Item($key) & @crlf)
        else
             ConsoleWrite($key & ":" & @crlf)
             PrintDict($dict.Item($key))
        endif
    next
endfunc

 

Share this post


Link to post
Share on other sites

Another way with index :

#include <String.au3>

$dict = ObjCreate("Scripting.Dictionary")
$dict.Add("Key10", "Value1")
$dict.Add("Key11", "Value2")
$dict.Add("Key2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Add("Sub-Key0", "Sub-Item1")
$dict.Item("Key2").Add("Sub-Key-2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Item("Sub-Key-2").Add("Sub-Sub-Key", "Sub-Sub-Item")
$dict.Item("Key2").Add("Sub-Key1", "Sub-Item2")
$dict.Add("Key3", "Value3")

ConsoleWrite ("dictionnary = {" & @CRLF)
PrintDict($dict, 1)

Func PrintDict ($oDic, $lvl)
  For $i = 0 to $oDic.count - 1
    If IsObj($oDic.items[$i]) Then
      ConsoleWrite (_StringRepeat(@TAB, $lvl) & $oDic.keys[$i] & ": {" & @CRLF)
      PrintDict($odic.items[$i], $lvl+1)
    Else
      ConsoleWrite (_StringRepeat(@TAB, $lvl) & $oDic.keys[$i] & ": " & $oDic.items[$i] & @CRLF)
    EndIf
  Next
  ConsoleWrite (_StringRepeat(@TAB, $lvl-1) & "}" & @CRLF)
EndFunc

 

Share this post


Link to post
Share on other sites

This is crying out for JSON. The easiest way is to use one of the UDFs that supports serialisation.

Example with the UDF from the appendix:

#include <JSON.au3>

$dict = ObjCreate("Scripting.Dictionary")
$dict.Add("Key10", "Value1")
$dict.Add("Key11", "Value2")
$dict.Add("Key2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Add("Sub-Key0", "Sub-Item1")
$dict.Item("Key2").Add("Sub-Key-2", ObjCreate("Scripting.Dictionary"))
$dict.Item("Key2").Item("Sub-Key-2").Add("Sub-Sub-Key", "Sub-Sub-Item")
$dict.Item("Key2").Add("Sub-Key1", "Sub-Item2")
$dict.Add("Key3", "Value3")

$sSerialized = _JSON_Generate($dict)

ConsoleWrite($sSerialized)

 

JSON.au3

Share this post


Link to post
Share on other sites

calling them back the way trancexx suggested in the above thread is the only way dictionary in dictionary ever really played nice for me (the add keyvaluepair function is just a wrapped add).

Edited by iamtheky

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...