shEiD Posted April 21, 2010 Posted April 21, 2010 Also, x_display() has been updated so you can new view the contents of regular arrays that are stored using this method. Try: Local $myArray[2][2] = [[1,2],[3,4]] x( 'some.key' , $myArray ) x_display() Does not show values, here's the output: Array ( [some] => Array ( [key] => Array[2][2] ( [0] => [1] => [0] => [1] => ) ) ) And it would (maybe) easier to read if elements would displayed like so: Array ( [some] => Array ( [key] => Array[2][2] ( [0][0] => [0][1] => [1][0] => [1][1] => ) ) )
OHB Posted April 21, 2010 Author Posted April 21, 2010 Does not show values, here's the output: Array ( [some] => Array ( [key] => Array[2][2] ( [0] => [1] => [0] => [1] => ) ) ) And it would (maybe) easier to read if elements would displayed like so: Array ( [some] => Array ( [key] => Array[2][2] ( [0][0] => [0][1] => [1][0] => [1][1] => ) ) ) Yeah it's supposed to. I had it working before...let me check the code. In the meantime, go check out your x_unset function
shEiD Posted April 21, 2010 Posted April 21, 2010 On the plus-side, there's now an x_unset() function.Grab your updated code above.
OHB Posted April 21, 2010 Author Posted April 21, 2010 (edited) Ah...me and my typos. Code updated to fix the array display problem. $idNum &= '[' & $a & ']' should be $idName &= '[' & $a & ']' It'll even handle regular arrays in regular arrays or associative arrays in regular arrays, and any combination you can think of. Try something like x( 'myObj.hello' , 'world' ) Local $myObj = x( 'myObj' ) Local $myArray[2][2] = [[1,2],[3,4]] Local $myArray2[2][2] = [[$myArray,$myObj],[$myArray,$myObj]] x( 'some.key' , $myArray2 ) x_display() Thanks! Edited April 21, 2010 by OHB
shEiD Posted April 21, 2010 Posted April 21, 2010 (edited) Try something like x( 'myObj.hello' , 'world' ) Local $myObj = x( 'myObj' ) Local $myArray[2][2] = [[1,2],[3,4]] Local $myArray2[2][2] = [[$myArray,$myObj],[$myArray,$myObj]] x( 'some.key' , $myArray2 ) x_display() Freakin awesome. Though for me (programing hobbyist and nothing more), this labyrinth is mind bending I would spend hours figuring out where I put my values Edited April 21, 2010 by shEiD
shEiD Posted April 21, 2010 Posted April 21, 2010 I already started rewriting some of my scripts, and noticed something:I mistakenly tried clearing the array with x(), but then realised, that you I need to provide x('','') for it work. And just thought, maybe it would be easier to changeIf @NumParams == 2 Then $func = "set"toIf @NumParams <> 1 Then $func = "set"then array could be cleared with simple x()Just a thought...
OHB Posted April 21, 2010 Author Posted April 21, 2010 I already started rewriting some of my scripts, and noticed something: I mistakenly tried clearing the array with x(), but then realised, that you I need to provide x('','') for it work. And just thought, maybe it would be easier to change If @NumParams == 2 Then $func = "set"toIf @NumParams <> 1 Then $func = "set"then array could be cleared with simple x() Just a thought... Good idea! Code updated.
Shafayat Posted April 21, 2010 Posted April 21, 2010 This is constantly improving and becoming a very useful and complete udf. So, you might like to post a zip file with all the stuffs so that lazy people like me have to in through less trouble. Keep up the good work. [Not using this account any more. Using "iShafayet" instead]
shEiD Posted April 25, 2010 Posted April 25, 2010 (edited) I've used it for these couple of days and it makes my scripting so much easier A couple of things, maybe: 1. Add the declarations for local variables in functions, because it gives error, if you use Opt('MustDeclareVars', 1) 2. Added fix to x_unset(), because it gave COM error, when trying to unset non existing key: Func x_unset($sKey) If $sKey == '' Then Return x('', '') $parts = StringSplit($sKey, ".") $cur = $_xHashCollection For $x = 1 To $parts[0] - 1 If Not $cur.exists($parts[$x]) Then Return False $cur = $cur.item($parts[$x]) Next If Not $cur.exists($parts[$parts[0]]) Then Return False ; <- Added this line $cur.remove($parts[$parts[0]]) Return True EndFunc ;==>x_unset 3. Add the support for "Opt("GUIOnEventMode", 1)" in x_display(). To be honest, I didn't know how to do that, but I suddenly remembered that _ArrayDisplay worked always, no matter what GUIOnEventMode was in the script. So I looked it up, and it works Func x_display($key = '') $iOnEventMode = Opt("GUIOnEventMode", 0) ; <- added this line $text = $key If $key <> '' Then $text &= " " $text &= StringTrimRight( _x_display( x($key), ''), 2) $wHnd = GUICreate("Array " & $key, 700, 500) GUISetState(@SW_SHOW, $wHnd) $block = GUICtrlCreateEdit($text, 5, 5, 690, 490) GUICtrlSetFont($block, 10, 400, -1, 'Courier') While 1 If GUIGetMsg() == -3 Then ExitLoop WEnd GUISetState(@SW_HIDE, $wHnd) GUIDelete($wHnd) Opt("GUIOnEventMode", $iOnEventMode) ; <- added this line EndFunc ;==>x_displayThanks goes to: (from _ArrayDisplay() UDF) ; Author ........: randallc, Ultima ; Modified.......: Gary Frost (gafrost), Ultima, Zedna, jpm (4). Maybe add "name" variable to x_display() function. This one's maybe not needed, but it's convenient, ie: if you want to display the same array before and after changes. The change makes no diference in usage whatsoever, just an option; (5). Maybe add 0x00CF0000 ($WS_OVERLAPPEDWINDOW) to GuiCreate. Its nice to have resizeable and maximizeable window: Func x_display($key = '', $name = '') ; <- modify $title = 'Array(' & $key & ')' ; <- add If @NumParams > 1 Then $title &= ' ' & $name ; <- add ... $wHnd = GUICreate($title, 700, 500, -1, -1, 0x00CF0000) ; <- modify ... Edited April 27, 2010 by shEiD
tito Posted August 9, 2010 Posted August 9, 2010 (edited) How can I simulate a Ubound using this UDF ? So far I have this function but it can only count 'root' arrays, not the subarrays within an array... Can someone pls help me adjust this funtion ? Func x_count( $sKey ) $cur = $_xHashCollection If ($cur.exists( $sKey )) Then $item = $cur.item( $sKey ) Return $item.count Else Return False EndIf EndFunc x('a.b.c', 'ok') x_count('a') works x_count('a.b') doesn't work... Edited August 9, 2010 by tito
tito Posted August 17, 2010 Posted August 17, 2010 bump... Can anyone help me in the right direction ? Howto count in deeper dimensions ? fe: text.en.name text.en.address.1.zip text.fr.name text.fr.address.1.zip text.fr.address.2.zip text.count should be 2 (en & fr) text.en.count should be 2 (.name & .address) text.fr.count should be 2 (.name & .address) text.en.address.count should be 1 (.1) text.fr.address.count should be 2 (.1 & .2)
shEiD Posted August 17, 2010 Posted August 17, 2010 (edited) @ tito, I'm quite new at this, so please excuse any bugs Here you go. ; Name...........: x_count ; Description ...: Returns a count of items ; Syntax.........: x_count( $sKey ) ; Parameters ....: $sKey - the key ; Return values .: Success: count of items of a provided key ; x_count() returns count os keys on first level ; Failure: 0, set error to: ; -1 = the key is not an object, but an item with a value ; -2 = the key does not exist ; Author ........: shEiD (original "x" UDF by: OHB) Func x_count($sKey = '') If $sKey == '' Then Return $_xHashCollection.Count Local $cur = $_xHashCollection Local $parts = StringSplit($sKey, ".") For $x = 1 To $parts[0] If Not $cur.exists($parts[$x]) Then Return SetError(-2, 0, 0) $cur = $cur.item($parts[$x]) Next If Not IsObj($cur) Then SetError(-1, 0, 0) Return $cur.Count EndFunc ;==>x_count PS, love this UDF and use it on daily basis. Me-so-sad, that OHB is not updating it. Anyway, OHB, again... Edit: Changed return value to 0 and setting @Error to appropriate error values. Edited November 13, 2010 by shEiD
tito Posted August 19, 2010 Posted August 19, 2010 @ tito,I'm quite new at this, so please excuse any bugs Here you go.Yihaa, thx so much , it works perfectly!I've been using this udf a lot too. Also hope it'll be further developed, though it has everything I need now.
OHB Posted August 25, 2010 Author Posted August 25, 2010 PS, love this UDF and use it on daily basis. Me-so-sad, that OHB is not updating it. Anyway, OHB, again... Well, point-blankly, I'm not updating it because I don't /currently/ have a use for it. But I encourage ya'll to contribute to it. Make a fix...write a new function...whatever you thing makes it better. Then, send me a PM and I'll update the post
LWC Posted August 25, 2010 Posted August 25, 2010 (edited) Update: see v2 here. Here's my solution to convert INI files into this "x" method (based on this, but I've also supported mid-sentence comments): #include <associative.au3> ; the custom code from the OP $s_Config=@DesktopDir & '\MyIniTest.ini' For $i = 1 To 6 IniWrite($s_Config, "section 1", "Key" & $i, "val" & $i) Next For $i = 1 To 3 IniWrite($s_Config, "section 2", "Key" & $i, "val" & $i) Next ini_to_x($s_Config) x_display() Func ini_to_x($hIniLocation) ;Get All Sections Local $aSections = IniReadSectionNames($hIniLocation) If @error Then Return SetError(1, 0, 0) ;Get All The Keys and Values for Each section For $iCount = 1 To $aSections[0] $aKV = IniReadSection($hIniLocation, $aSections[$iCount]) If @error Then ; If empty section then ignore (treat as void) ContinueLoop EndIf For $xCount = 1 To $aKV[0][0] $value=StringSplit($aKV[$xCount][1],";") ; Support for mid-sentence comments $value=StringStripWS($value[1], 3) x($aSections[$iCount] & '.' & $aKV[$xCount][0], $value) Next Next EndFunc Edited November 9, 2023 by LWC Added v2 link
qsek Posted April 7, 2012 Posted April 7, 2012 (edited) Finally i have a reason to revive this thread, yay! I'm using this exellent UDF for quite a while now. I like the functional usage of x and its nearly as fast as using normal arrays. LWC's ini functions were helpful but i wanted more. So i've extended the ini functionality with the help of MilesAhead's snippets. With this you can manage several ini files, several sections and store lists in delimited strings. Example: expandcollapse popup#include <Array.au3> #include <AssoArrays.au3> $sConf = "config"; Name of the ini file ( '.ini' will be added automatically) $temp = FileOpen($sConf&".ini", 2); Create/Empty the ini file FileClose($temp) x($sConf&".general.option1","5") ; The name of the rootitem needs to be the same as the ini file name x($sConf&".general.option2","true") x($sConf&".general.option3","Admin") x($sConf&".profile1.value1","0") x($sConf&".profile1.value2","false") x($sConf&".profile1.value3","11") Dim $aIps1 = ["ip1","ip3","ip3"] x($sConf&".profile1.list1",$aIps1) x($sConf&".profile2.value1","1") x($sConf&".profile2.value2","false") x($sConf&".profile2.value3","12") Dim $aIps2 = ["ip4","ip5","ip6"] x($sConf&".profile2.list1",$aIps2) x("some_other_value","1") ; will not be saved in the config x_display(); array before writing to ini ConsoleWrite("-----------------------------------------------------" & @CRLF) _WriteAssocToIni($sConf) x_del($sConf); Delete config array x_display(); Show that array is deleted ConsoleWrite("-----------------------------------------------------" & @CRLF) _ReadAssocFromIni($sConf) x_display(); array restored from ini x_del($sConf&".profile2"); Delete profile2 section in array _WriteAssocToIni($sConf,"",1); Erase all content in ini before writing or else profile2 will stay in the ini Exit UDF with new functions: AssoArrays.au3 expandcollapse popup#include-once #include <GUIConstantsEx.au3> ; #INDEX# ======================================================================================================================= ; Title .........: xHashCollection ; AutoIt Version : 3.3.4.0 ; Language ......: English ; Description ...: Create and use Multidimentional Associative arrays ; Author ........: OHB <me at orangehairedboy dot com> ; =============================================================================================================================== ;~ $tt = TimerInit() Global $_xHashCollection = ObjCreate( "Scripting.Dictionary" ), $_xHashCache ;~ ConsoleWrite("Asso Array Load up time: "&Round(TimerDiff($tt) ) & @CRLF) ; #FUNCTION# ==================================================================================================================== ; Name...........: x ; Description ...: Gets or sets a value in an Associative Array ; Syntax.........: SET: x( $sKey , $vValue ) ; GET: x( $key ) ; Parameters ....: $sKey - the key to set or get. Examples: ; x( 'foo' ) gets value of foo ; x( 'foo.bar' ) gets value of bar which is a key of foo ; $bar = "baz" ; x( 'foo.$bar' ) gets value of baz which is a key of foo (variables are expanded) ; Return values .: Success - When setting, return the value set. When getting, returns the requested value. ; Failure - Returns a 0 ; Author ........: OHB <me at orangehairedboy dot com> ; =============================================================================================================================== Func x( $sKey = '' , $vValue = '' ) $func = "get" If @NumParams <> 1 Then $func = "set" If $sKey == '' Then If $func == "get" Then Return $_xHashCollection Else $_xHashCollection.removeAll Return '' EndIf EndIf $parts = StringSplit( $sKey , "." ) $last_key = $parts[$parts[0]] $cur = $_xHashCollection For $x = 1 To $parts[0] - 1 If Not $cur.exists( $parts[$x] ) Then If $func == "get" Then Return $cur.add( $parts[$x] , ObjCreate( "Scripting.Dictionary" ) ) EndIf $cur = $cur.item( $parts[$x] ) Next If IsPtr( $vValue ) Then $vValue = String( $vValue ) If $func == "get" Then If Not $cur.exists( $last_key ) Then Return $item = $cur.item( $last_key ) Return $item ElseIf Not $cur.exists( $last_key ) Then $cur.add( $last_key , $vValue ) Else $cur.item( $last_key ) = $vValue EndIf Return $vValue EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: x_del ; Description ...: Removes a key from an Associative Array ; Syntax.........: x_del( $sKey ) ; Parameters ....: $sKey - the key to remove. ; Return values .: Success - True ; Failure - False ; Author ........: OHB <me at orangehairedboy dot com> ; =============================================================================================================================== Func x_del( $sKey ) If $sKey == '' Then Return x( '' , '' ) $parts = StringSplit( $sKey , "." ) $cur = $_xHashCollection For $x = 1 To $parts[0] - 1 If Not $cur.exists( $parts[$x] ) Then Return False $cur = $cur.item( $parts[$x] ) If Not IsObj($cur) Then Return False Next If Not $cur.exists( $parts[$parts[0]] ) Then Return False $cur.remove( $parts[$parts[0]] ) Return True EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: x_display ; Description ...: Displays the contents of an Associative Array ; Syntax.........: x_display( $sKey ) ; Parameters ....: $sKey - the key to display. Examples: ; x_display() displays everything ; x_display( 'foo' ) displays the contents of foo ; Author ........: OHB <me at orangehairedboy dot com> ; =============================================================================================================================== Func x_display( $key = '' ) $text = $key If $key <> '' Then $text &= " " $text &= StringTrimRight( _x_display( x( $key ) , '' ) , 2 ) ConsoleWrite($text & @LF) $wHnd = GUICreate( "Array " & $key , 700 , 500 ) GUISetState( @SW_SHOW , $wHnd ) $block = GUICtrlCreateEdit( $text , 5 , 5 , 690 , 490 ) GUICtrlSetFont( $block , 10 , 400 , -1 , 'Courier' ) While 1 If GUIGetMsg() == -3 Then ExitLoop WEnd GUISetState( @SW_HIDE , $wHnd ) GUIDelete( $wHnd ) EndFunc ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: _x_display ; Description ...: Itterates through an array and builds output for x_display ; Author ........: OHB <me at orangehairedboy dot com> ; =============================================================================================================================== Func _x_display( $item , $tab ) If IsObj( $item ) Then $text = 'Array (' & @CRLF $itemAdded = False For $i In $item $text &= $tab & " [" & $i & "] => " & _x_display( $item.item($i) , $tab & " " ) $itemAdded = True Next If Not $itemAdded Then $text &= @CRLF $text &= $tab & ')' ElseIf IsArray( $item ) Then $text = "Array" $totalItems = 1 $dimensions = UBound( $item , 0 ) For $dimension = 1 To $dimensions $size = UBound( $item , $dimension ) $totalItems *= $size $text &= "[" & $size & "]" Next $text &= " (" & @CRLF For $itemID = 0 To $totalItems - 1 $idName = '' $idNum = $itemID For $dimension = 1 To $dimensions - 1 $mul = ( $totalItems / UBound( $item , $dimension ) ) $a = Floor( $idNum / $mul ) $idName &= '[' & $a & ']' $idNum -= ( $a * $mul ) Next $idName &= '[' & $idNum & ']' $text &= $tab & " " & $idName & " => " & _x_display( Execute( "$item" & $idName ) , $tab & " " ) Next $text &= $tab & ")" Else $text = $item EndIf $text &= @CRLF Return $text EndFunc ; Name...........: x_count ; Description ...: Returns a count of items ; Syntax.........: x_count( $sKey ) ; Parameters ....: $sKey - the key ; Return values .: Success: count of items of a provided key ; x_count() returns count os keys on first level ; Failure: 0, set error to: ; -1 = the key is not an object, but an item with a value ; -2 = the key does not exist ; Author ........: shEiD (original "x" UDF by: OHB) Func x_count($sKey = '') If $sKey == '' Then Return $_xHashCollection.Count Local $cur = $_xHashCollection Local $parts = StringSplit($sKey, ".") For $x = 1 To $parts[0] If Not $cur.exists($parts[$x]) Then Return SetError(-2, 0, 0) $cur = $cur.item($parts[$x]) Next If Not IsObj($cur) Then SetError(-1, 0, 0) Return $cur.Count EndFunc ;==>x_count ; Author: MilesAhead ; http://www.autoitscript.com/forum/topic/110768-itaskbarlist3/page__view__findpost__p__910631 ;write AssocArray to IniFile Section ;returns 1 on success - sets @error on failure Func _WriteAssocToIni($myIni = 'config.ini', $mySection = '', $bEraseAll = false, $sSep = "|") If Not StringInStr($myIni,".") Then $myIni &= ".ini" If $bEraseAll then $temp = FileOpen($myIni, 2) FileClose($temp) EndIf Local $sIni = StringLeft($myIni,StringInStr($myIni,".")-1) If Not $_xHashCollection.Exists($sIni) Then Return SetError(-1, 0, 0) If $mySection == '' Then $aSection = $_xHashCollection($sIni).Keys(); All sections Else Dim $aSection[1] = [$mySection]; specific Section EndIf Local $retVal = 0 For $i = 0 To UBound($aSection)-1 $cur = x($sIni&"."&$aSection[$i]) $retVal = 0 If $cur.Count() < 1 Then Return SetError(-2, 0, 0) EndIf Local $iArray[$cur.Count()][2] Local $aArray = $cur.Keys() For $x = 0 To UBound($aArray) - 1 $iArray[$x][0] = $aArray[$x] $value = x($sIni&"."&$aSection[$i]&"."&$aArray[$x]) If IsArray($value) then $iArray[$x][1] = _MakePosString($value, $sSep) Else $iArray[$x][1] = $value EndIf Next $retVal = IniWriteSection($myIni, $aSection[$i], $iArray, 0) next Return SetError(@error, 0, $retVal) EndFunc ;==>_WriteAssocToIni ;read AssocArray from IniFile Section ;returns number of items read - sets @error on failure Func _ReadAssocFromIni($myIni = 'config.ini', $mySection = '', $sSep = "|") If Not StringInStr($myIni,".") Then $myIni &= ".ini" Local $sIni = StringLeft($myIni,StringInStr($myIni,".")-1) If $mySection == '' Then $aSection = IniReadSectionNames ($myIni); All sections If @error Then Return SetError(@error, 0, 0) Else Dim $aSection[2] = [1,$mySection]; specific Section EndIf For $i = 1 To UBound($aSection)-1 Local $sectionArray = IniReadSection($myIni, $aSection[$i]) If @error Then Return SetError(-1, 0, 0) For $x = 1 To $sectionArray[0][0] If StringInStr($sectionArray[$x][1], $sSep) then $posS = _MakePosArray($sectionArray[$x][1], $sSep) Else $posS = $sectionArray[$x][1] EndIf x($sIni&"."&$aSection[$i]&"."&$sectionArray[$x][0], $posS) Next next Return $sectionArray[0][0] EndFunc ;==>_ReadAssocFromIni ;makes a Position string using '#' number separator Func _MakePosString($posArray, $sSep = "|") Local $str = "" For $x = 0 To UBound($posArray) - 2 $str &= String($posArray[$x]) & $sSep Next $str &= String($posArray[UBound($posArray) - 1]) Return $str EndFunc ;==>_MakePosString ;makes a Position array from a Position string Func _MakePosArray($posString, $sSep = "|") Return StringSplit($posString, $sSep, 2) EndFunc ;==>_MakePosArray  Edited November 5, 2023 by qsek Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite
robinsiebler Posted June 7, 2012 Posted June 7, 2012 (edited) I want to have an INI section that looks like this: [Products] C3Communicator.Name=Avistar C3 Communicator C3Communicator.Folder=Avistar C3 Communicator C3Communicator.Installer=C3CommunicatorSetup.msi However, I cannot figure out how to access Name, Folder, and Installer. I can't figure out how to access [0], [1], or [2] either: [Products] ;internal name = Display Name | Folder Name | Installer C3Communicator=Avistar C3 Communicator|Avistar C3 Communicator|C3CommunicatorSetup.msi CitrixRTME=Citrix RealTime Media Engine|Citrix HDX|Citrix HDX RealTime Media Engine.msi CitrixRTC=Citrix RealTime Connector|Citrix HDX|HDX RealTime Connector LC.msi C3Unified=Avistar C3 Unified|C3 Unified - Microsoft Lync Edition|C3UnifiedLyncSetup.msi [Products] => Array ( [C3Communicator] => Array[3] ( [0] => Avistar C3 Communicator [1] => Avistar C3 Communicator [2] => C3CommunicatorSetup.msi Edited June 7, 2012 by robinsiebler
robinsiebler Posted June 7, 2012 Posted June 7, 2012 (edited) I couldn't figure out how to get the 1st INI layout to work at all. I think it is a bug in _ReadAssocFromIni(). However, I finally figured out how to get the 2nd layout:GetProducts() MsgBox(0, x("CitrixRTC.Name"), "Folder: " & x("CitrixRTC.Folder") & @CRLF & " Installer: " & x("CitrixRTC.Installer")) Func GetProducts() For $entry in x($sConf&'.Products') $foo = StringSplit(x($sConf&'.Products.'&$entry), ":", 2) For $count = 0 to 2 Select Case $count = 0 x($entry&".Name", $foo[0]) Case $count = 1 x($entry&".Folder", $foo[1]) Case $count = 2 x($entry&".Installer", $foo[2]) EndSelect Next $Products = $Products & $entry & "|" Next $Products = StringSplit(StringTrimRight($Products, 1), "|", 2) EndFunc Edited June 7, 2012 by robinsiebler
zorphnog Posted June 7, 2012 Posted June 7, 2012 I want to have an INI section that looks like this: [Products] C3Communicator.Name=Avistar C3 Communicator C3Communicator.Folder=Avistar C3 Communicator C3Communicator.Installer=C3CommunicatorSetup.msi However, I cannot figure out how to access Name, Folder, and Installer. $sConf = "config" ; Assuming your .ini file is named config _ReadAssocFromIni($sConf) $sMsg = StringFormat("Folder: %snInstaller: %s", x($sConf & ".Products.C3Communicator.Folder"), x($sConf & ".Products.C3Communicator.Installer")) MsgBox(0, x($sConf & ".Products.C3Communicator.Name"), $sMsg)
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now