Jump to content
Sign in to follow this  
Squirrely1

Create Associative Arrays with WSC ?

Recommended Posts

Squirrely1

I noticed there has been quite a bit of interest in creating an associative array functionality. What I have seen so far might be very useful to some people, but I was thinking it would be great if you there was a single function that would create your array, and maybe another one for creating array keys and from there on you could access the data stored under that key just with something like this:

MsgBox(0, "", $oSquirrel.nuts)

Other attempts at creating this functionality involve business that makes the data you want to access, no simpler to get to than is offered by VBScript's "Scripting.Dictionary" object - you have to call a function to get anything done - they're using complicated array hash algorithms and stuff.

I came across this old link where ptrex found a way to create custom objects:

Create COM objects without need of DLL's - (ptrex)

Now I'm not quite a good enough programmer to create this associative array functionality myself, but if this Windows Script Component Wizard way might work to create this functionality, he would be a popular person who was able to do it. Maybe it could be done with wsc

Even if it could only store strings and numbers, I would use it quite a bit - but if it could store handles and objects, that would be the most.

Here's a link to the MSDN article on WSC and Wizards:

http://msdn.microsoft.com/en-us/library/7531dsc9(VS.85).aspx

Edited by Squirrely1

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites
weaponx

I think the dictionary object is pretty nice. It's slower writing to it than an array but retrieval times are non-existent. Still, the associative array should be native.

This creates a haystack and hides a needle in it, measuring write/read times:

$testSize = 100000
$keyword = "ZEBRA"

;---------------------------------------
;OBJECT TEST - RETRIEVE SPECIFIC VALUE
;---------------------------------------
$timer1a = TimerInit()
$obj = ObjCreate("Scripting.Dictionary")

For $X = 0 to $testSize-1
    $obj.Add(RandomString(), $X)
Next

;Add specific value to find
$obj.Add($keyword, "value")

$total1a = TimerDiff($timer1a) / 1000

;Benchmark
$timer1b = TimerInit()
ConsoleWrite($obj.Item($keyword) & @CRLF)
$total1b = TimerDiff($timer1b) / 1000

;---------------------------------------
;ARRAY TEST - RETRIEVE SPECIFIC VALUE
;---------------------------------------
$timer2a = TimerInit()
Dim $array[$testSize][2]

;Populate array with random strings
For $X = 0 to $testSize - 1
    $array[$X][0] = RandomString()
    $array[$X][1] = "value"
Next

;Add specific value to find, for worst case place at end of array
$array[$testSize/2][0] = $keyword

$total2a = TimerDiff($timer2a) / 1000

;Benchmark
$timer2b = TimerInit()
For $X = 0 to $testSize - 1
    If $array[$X][0] = $keyword Then
        ConsoleWrite($array[$X][1] & @CRLF)
        ExitLoop
    EndIf
Next
$total2b = TimerDiff($timer2b) / 1000

$msg = "Object W: " & $total1a & " s" & @CRLF
$msg &= "Object R: " & $total1b & " s" & @CRLF
$msg &= "Array W: " & $total2a & " s" & @CRLF
$msg &= "Array R: " & $total2b & " s" & @CRLF

MsgBox(0,"",$msg)

;Retrieve random string
Func RandomString()
    ;Generate random 8 character string
    $string = ""
    For $X = 0 to 7
        $string &= Chr(Random(65,90,1))
    Next
    Return $string
EndFuncoÝ÷ Ù¬º[Nn7µn9ÓÞ7ãßt÷^=òÃç-GM4Ó^:óNvÓz÷®¶°
ëk%·÷]÷óÝ}÷Ny÷Û®¶²GMxÛ
Edited by weaponx

Share this post


Link to post
Share on other sites
Squirrely1

That works pretty good; here are some functions DaleHolm wrote, but it still involves a function call, getting the data:

$squirrely = _Hash_Create()

_Hash_KeyAdd($squirrely, "food", "nuts & bark")

MsgBox(0, "I just want to use $squirrely.food", _
    "Couldn't just bump on $squirrely.food: " & @CR & _Hash_KeyGetValue($squirrely, "food"))

;MsgBox(0, "", $squirrely.beast)
;Ref - http://msdn.microsoft.com/en-us/library/7531dsc9(VS.85).aspx
;   http://www.autoitscript.com/forum/index.php?showtopic=38671&st=15
;---------------------------------
; Hash.au3
;---------------------------------
; EXAMPLE:
;
; $oHash = _HashCreate()
; _Hash_KeyAdd($oHash, "Color", "Blue")
; _Hash_KeyAdd($oHash, "Shape", "Round")
; ConsoleWrite("Color: " & _Hash_KeyGetValue($oHash, "Color") & ", " & "Shape: " & _Hash_KeyGetValue($oHash, "Shape") & @CR)
;---------------------------------

; Create a new Hash (Dictionary) Object
Func _Hash_Create()
    Return ObjCreate("Scripting.Dictionary")
EndFunc

; Add a ney Key/Value pair
Func _Hash_KeyAdd($o_object, $v_key, $v_value = "")
    $o_object.add ($v_key, $v_value)
EndFunc

; Get the value associated with a key
Func _Hash_KeyGetValue($o_object, $v_key)
    Return $o_object.item ($v_key)
EndFunc

I don't think this functionality will be very popular to everyday scripters like me.

But you can create a $squirrely.food property that is read/write if you have a COM object created with .wsc code of this sort ...

<public>
   <property name="sname" dispid="0"/>
   <property name="age" dispid="0">
      <get internalName="readAge"/>
   </property>
   <property name="dateOfBirth" dispid="0">
      <get internalName="readDOB"/>
      <put internalName="writeDOB"/>
   </property>
</public>

<script language="VBScript">
<![CDATA[
Dim sname   ' Read-write sname property (no functions).
Dim gDOB   ' Global variable used to store date of birth.

Function readDOB()
   ' Gets value of dateOfBirth property.
   readDOB = gDOB
End Function

Function writeDOB(newDOB)
   ' Sets value of dateOfBirth property.
   If isDate(gDOB) Then
      'Error checking
      gDOB = newDOB
   End If
End Function

Function readAge()
   ' Calculates read-only age property.
   If isDate(gDOB) Then
      dobM = DatePart("m", gDOB)
      dobD = DatePart("d", gDOB)
      dobY = DatePart("yyyy", gDOB)
      todayY = DatePart("yyyy", Date)
      age = todayY - dobY

      ' Adjust if birthday has not yet occurred this year.
      bday = DateValue(dobM & "/" & dobD & "/" & todayY)
      If DateDiff("d", bday, DateValue(Date)) < 0 Then
         age = age - 1
      End If
      readAge = age
   End If
End Function
]]>
</script>

The code above does NOT actually create that object and that property, it is only an example from the MSDN of a .wsc file of a sort that I'm pretty sure can create that functionality.

I am almost positive that the ability I want can be accomplished with the XML DOM and I started to work on it. But then it came to mind that it might never work to store objects and handles. Then I came across ptrex's code, and from what they were saying about it in that thread, it seemed that with the right vbscript in the .wsc file, any kind of data perhaps be stored as a property.

Edited by Squirrely1

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites
weaponx

I don't see a need for a UDF to wrap the Scripting.Dictionary, it is much easier to use the simple syntax I showed in the example.

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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.