Discussion:
Is there a BETTER way to work with arrays?
(too old to reply)
JJ
2018-04-15 08:36:27 UTC
Permalink
I frequently need to use one dimensional arrays for e.g.: search a value in
a array, sort the array, copy part or whose array, etc.

But there isn't any built in function to do basic task with array except:
Array, Dim, Erase, IsArray, LBound, ReDim, and UBound.

I had to create my own functions for those. e.g. for searching a value in an
array:

function indexof(arr, val)
indexof = -1
for i = 0 to ubound(arr)
if arr(i) = val then
indexof = i
exit function
end if
next
end function

dim arr(2)
arr(0) = 3
arr(1) = 9
arr(2) = 1
wscript.echo indexof(arr, 5) '-1
wscript.echo indexof(arr, 1) '2

So, if anyone know a better way to work with array, I'm all ears.

Currently, I had keep a VBS file that contains subroutines and functions, as
a library. I'd copy+paste any required code from the file into the main VBS
script in order to make them available. This can be a tedious task when many
functions are involved. Moreover the main VBS script would be cluttered.

How did you do for this case?
Mayayana
2018-04-15 12:41:31 UTC
Permalink
"JJ" <***@vfemail.net> wrote

| How did you do for this case?

I guess you could use a class. I just use it inline.
To me that's simpler. Also, I typically have more
complexity. There might be multiple loops. A fluff
code sample:

Do While x > 0
For i = 0 to UBound(a1)
.....
Next
If y > 2 then
For i2 = 0 to UBound(A2)
if A2(i2) > 3 and A2(i2) < 15 and t = 0 then
....
End if
Next
End If
Loop

None of that is going to transfer easily to a class.

I mostly just focus on efficiency. In fact,
I prefer not to make things too "object
oriented" because that makes it difficult to
follow the code logic.

So I use arrays for things like string
concatenation. I assign UBound to a variable
if I intend to use it multiple times. Things like
that. But writing loops doesn't seem like a
hassle to me.
R.Wieser
2018-04-15 14:35:26 UTC
Permalink
JJ,
Is there a BETTER way to work with arrays?
You're confusing me: You're describing a problem with having to
copy-and-paste generic routines into a new project, but your question is
about working with arrays ...

In other words, what *is* the problem ?

If its that copy-and-paste, than you could take a look at the "execute"
command to create a kind of "include" command (to load one or more
"libraries" of generic VBS functions)

If its the code in regard to searching thru a column of an array, than you
have a few possibilities:

If you just want a faster search method than you could use a binary one.
But the drawback of that is that you would need to make/keep the column you
search thru sorted.

Another possibility is to use a dictionary object. Ofcourse, it comes with
its own drawbacks. The data in the first column must be unique, and it
will automatically sort it. It also only allows two columns. On top of
that it doesn't allow "by index" access.

You could also use a dictionary object to duplicate a certain column of a
standard array (with the columns data in its first, and the index to the
origional data in the second column) so you can search fast and retrieve the
index to the rest of the data.

Ofcourse, all of the above means *more* code you will have to manage, not
less. So the question of if the above would be "better" therefore fully
depends on what you're after.

One thing I almost forgot: You can ofcourse also try to find or create your
own "array object" (creeating one is less complex than you might think.
Windows pretty-much already supports it with its DSA_* family of functions).
:-)

Regards,
Rudy Wieser
k***@gmail.com
2019-03-19 18:37:09 UTC
Permalink
Post by JJ
I frequently need to use one dimensional arrays for e.g.: search a value in
a array, sort the array, copy part or whose array, etc.
Array, Dim, Erase, IsArray, LBound, ReDim, and UBound.
I had to create my own functions for those. e.g. for searching a value in an
function indexof(arr, val)
indexof = -1
for i = 0 to ubound(arr)
if arr(i) = val then
indexof = i
exit function
end if
next
end function
dim arr(2)
arr(0) = 3
arr(1) = 9
arr(2) = 1
wscript.echo indexof(arr, 5) '-1
wscript.echo indexof(arr, 1) '2
So, if anyone know a better way to work with array, I'm all ears.
Currently, I had keep a VBS file that contains subroutines and functions, as
a library. I'd copy+paste any required code from the file into the main VBS
script in order to make them available. This can be a tedious task when many
functions are involved. Moreover the main VBS script would be cluttered.
How did you do for this case?
Switch your calling scripts to WSF file format and in them refer to your
shared array routines library vbs file via a <script> tag. You can include
a file path & name the file .inc instead of .vbs if it helps you remember.

Include it early on IN EACH JOB in the WSF & it will be executed before
your jobs' other scripts. Don't put any naked commands in it, as they
will be executed, just define constants & routines you may want to call.

<?xml?>
<package>
<comment>Jobs using my array library ArrayLibrary.vbs
cscript TestArray.wsf //job:Job1
cscript TestArray.wsf //job:Job2
</comment>
<resource id="1234">Text String or Number</resource>
<resource id="ArraySize">25</resource>
<job id="Job1">
<comment>First test of array routine</comment>
<object id="WshShell" progid="Wscript.Shell" />
<object id="FSO" progid="Scripting.FileSystemObject" />
<reference object="Wscript.Shell" />
<reference object="Scripting.FileSystemObject" />
<script language="VBScript" src="ArrayLibrary.vbs"/>
<script language="VBScript">
<![CDATA[
' WshShell & FSO global objects defined + all their typelib'd constants
' ArrayLibrary.vbs ran so all its routines are defined to me.
Dim I , J , arrTest()
ReDim arrTest( getResource("ArraySize") )
J = UBound(arrTest) ' make array most unsorted possible (rev sort).
' note LBound() UBound() & Len() are instant memory lookups
' and even UBound() - 1 is only calc'd 1 time for the For Loop's existance.
' no need to assign them to variables.
For I = LBound(arrTest) To UBound(arrTest)
arrTest(I) = J : J = J - 1
Next
SortArray(arrTest) ' call sort routine in ArrayLibrary.vbs
wscript.echo Join(arrTest, vbLf) ' show it 1 line per entry.
'if you Quit here, the following script in this job will never run.
' WScript.Quit
]]>
</script>
<script language="JavaScript">
<![CDATA[
// a javascript routine can go here.
function ReverseDemo(){
var a, l; //Declare variables.
a = new Array(0,1,2,3,4); //Create an array and populate it.
l = a.reverse(); //Reverse the contents of the array.
return(l); //Return the resulting array.
}
]]>
</script>
</job>
<job id="Job2">
<comment>Second test job of array routine</comment>
<reference object="Scripting.Dictionary" />
<object id="oDict" progid="Scripting.Dictionary" />
<comment>library .inc now in includes dir next to script dir</comment>
<script language="VBScript" src="..\includes\ArrayLibrary.inc"/>
<script language="VBScript">
<![CDATA[
wscript.echo "hello from TestArray Job2"
Const BinaryCompare = 0 ' same as vbBinaryCompare
Const TextCompare = 1 ' same as vbTextCompare
Const DatabaseCompare = 2
Dim arrKeys, arrItems
With oDict
' Optional: can be 0 (Binary), 1 (Text), 2 (Database)
' Values greater than 2 can be used for specific Locale IDs (LCID).
' use binary if case sensitive keys, use text if case insensitive keys.
' .CompareMode = 0
.Add "key" , "item" ' add a new key & Item pair to the dictionary.
' .Count ' # of key/item pairs in dictionary
' .Exists(key) ' bool True if key exists in dict
' .Key(key) = NewKey ' change key value for an item.
' myItem = .Item(key) ' get an item value for a key.
' .Item(key) = NewItem ' set an item value for a key.
' .Remove(key) ' remove a given Key and its Item entry from the dict.
' .RemoveAll ' delete all keys and values
' its faster to Set oDict = Nothing : Set oDict = CreateObject("Scripting.Dictionary")
' copy key and item lists into new 1D arrays!
arrKeys = .Keys
arrItems = .Items
.RemoveAll
End With ' oDict
WScript.Echo Join(arrKeys) , Join(arrItems)
Erase arrKeys : Erase arrItems

' use .Count as key 0..N For an ordered FIFO list of keyless items.
With oDict
For I = 0 To 10 : .Add .Count , "Item " & CStr(I) : Next
' copy key and item lists into new 1D arrays!
arrKeys = .Keys : arrItems = .Items
End With ' oDict
' ForEach walks dictionary KEYS in order ADDED, use .Item(v) for matching value.
For Each v In oDict
WScript.Echo v , oDict.Item(v)
Next
WScript.Echo Join(arrKeys) , Join(arrItems)
' test a function in ArrayLibrary.inc
WScript.Echo IndexOf(arrKeys,6)
Erase arrKeys : Erase arrItems

Dim ab(2,3)
ab(0,0) = "0,0" : ab(0,1) = "0,1" : ab(0,2) = "0,2" : ab(0,3) = "0,3"
ab(1,0) = "1,0" : ab(1,1) = "1,1" : ab(1,2) = "1,2" : ab(1,3) = "1,3"
ab(2,0) = "2,0" : ab(2,1) = "2,1" : ab(2,2) = "2,2" : ab(2,3) = "2,3"

' ForEach on a matrix cycles thru all of the leftmost index first
' then increments the next dimension to the right and repeats, then
' it increments the next dimension to the right of that upto 60 dimensions
' Dim array1(columns, rows) to cycle thru all columns before moving to next row.
' Dim array1(rows, columns) to cycle thru all rows before moving to next column.
I = 0
For Each v In ab
WScript.Echo "Entry: ", I , v , " should be at " , I Mod 3 , I \ 3
I = I + 1
Next
]]>
</script>
</job>
</package>

Loading...