I need to create multi-dimensional array of strings. Each row of the array can have varying number of strings. Something like the follwing code:
twoDimension = Array(Array())
ReDim Preserve twoDimension(3)
For i = 0 to 2
If i = 1 Then
twoDimension(i) = Array(1,2,3)
End If
If i = 2Then
twoDimension(i) = Array(1,2,3,4,5)
End If
Next
How about a dictionary
Set a = CreateObject("Scripting.Dictionary")
a.Add 0, Array(1,2,3)
a.Add 1, Array(4,5,6)
MsgBox a.Count
MsgBox a.Item(0)(2)
MsgBox a.Item(1)(1)
There's nothing wrong with having jagged arrays in VBScript. There are some minor issues with your code (ReDim to 3 but only assigning values to 2, unnecessarily using a For loop to assign values), but in general, that's the correct syntax to use.
Option Explicit
Dim twoDimension, i, j
twoDimension = Array(Array())
ReDim Preserve twoDimension(2)
twoDimension(1) = Array(1,2,3)
twoDimension(2) = Array(1,2,3,4,5)
For i = 0 To UBound(twoDimension)
For j = 0 To UBound(twoDimension(i))
WScript.Echo "(" & i & "," & j & ") = " & twoDimension(i)(j)
Next
Next
Related
I have written code for an array of numbers which prints out. I'm now writing code to split the array into even and off numbers. I've started off with an if statement to separate the numbers but i'm struggling to find a solution on how to do it. My code below is failing as it's unable to split the numbers.
Sub main()
a=Array(5,10,15,20)
for each x in a
Msgbox(x)
If MyArray(I) / 2 = MyArray(I)
List1.AddItem MyArray(I) ' Even Integers
Else
List2.AddItem MyArray(I) ' Odd Integers
End if
next
End Sub
As Lankymart suggests, the simplest approach would be to use Mod() and check if the remainder is 1 or 0, but you can also do it with the approach you seemed to be working towards:
If MyArray(index)/2 = Int(MyArray(index)/2) Then
' Even number
Else
' Odd number
End If
Mod() approach:
If MyArray(index) Mod 2 = 0 Then
' Even number
Else
' Odd number
End If
Here's a complete subroutine that demonstrates what you are trying to do:
Dim arr(4) As Integer
Dim arrEven() As Integer
Dim iEvenValues As Integer
Dim arrOdd() As Integer
Dim iOddValues As Integer
Dim iCounter As Integer
' Initialize array
arr(0) = 5
arr(1) = 10
arr(2) = 15
arr(3) = 20
For iCounter = 1 To UBound(arr)
If arr(iCounter - 1) Mod 2 = 0 Then
iEvenValues = iEvenValues + 1
ReDim Preserve arrEven(iEvenValues)
arrEven(iEvenValues - 1) = arr(iCounter - 1)
Else
iOddValues = iOddValues + 1
ReDim Preserve arrOdd(iOddValues)
arrOdd(iOddValues - 1) = arr(iCounter - 1)
End If
Next
Dim sValues As String
sValues = "Even values (" & iEvenValues & "):"
For iCounter = 1 To UBound(arrEven)
sValues = sValues & " " & arrEven(iCounter - 1)
Next
MsgBox sValues
sValues = "Odd values (" & iOddValues & "):"
For iCounter = 1 To UBound(arrOdd)
sValues = sValues & " " & arrOdd(iCounter - 1)
Next
MsgBox sValues
I'm need to be able to have a 2d array, where the length of second array varies on a case by case basis. To this end, I made an array that contains other arrays with the following code:
Dim timeline
ReDim timeline(days)
for reDate = beginDate to endDate
timeline(DateDiff("d", beginDate, reDate)) = Array(0)
next
The problem I am having is that I am unable to change the size of any of the arrays contained by timeline, as ReDim doesn't seem to work when I do this. Does anyone know how I would go about this?
Try the below snippet, using a as temporary array variable:
Dim timeline, a
ReDim timeline(days)
' initial fill the array
For reDate = beginDate to endDate
a = Array()
ReDim a(99)
timeline(DateDiff("d", beginDate, reDate)) = a
Next
' redim sub arrays
For reDate = beginDate to endDate
' assign subarray to a
a = timeline(DateDiff("d", beginDate, reDate))
' redim a
ReDim Preserve a(199)
' put changed array into root array
timeline(DateDiff("d", beginDate, reDate)) = a
Next
In this case each subarray contains 100 elements first, and 200 after redim.
"Does not work" and error messages ("Object required") without code/context are not the best way to ask a question. The first is a complete waste of time; the second may indicate that you used Set where you shouldn't (VBScript Arrays are not objects, so there shouldn't be any Set in the code).
This demonstrates the same facts that #omegastripes pointed out, but gives hints wrt possible pitfalls:
Option Explicit
Dim AoA : AoA = Split("s o m e|w o r d s|o f|d i f f e r e n t|l e n g t h", "|")
Dim i
For i = 0 To UBound(AoA)
AoA(i) = Split(AoA(i))
Next
WScript.Echo "----- test data:"
For i = 0 To UBound(AoA)
WScript.Echo Join(AoA(i), "")
Next
WScript.Echo "----- array assignment copies (For Each elem ... does not 'work'):"
Dim e
For Each e In AoA
e = "zap"
Next
For Each e In AoA
WScript.Echo Join(e, "")
Next
WScript.Echo "----- array assignment copies (change needs index access):"
For i = 0 To UBound(AoA)
e = AoA(i)
e(0) = UCase(e(0)) ' just changes the copy (e)
WScript.Echo Join(e, "")
AoA(i)(1) = UCase(AoA(i)(1)) ' access via indices changes org collection
WScript.Echo Join(AoA(i), "")
Next
WScript.Echo "----- replace whole subarrays (re-dimensioned dynamically):"
Dim n, m
For i = 0 To UBound(AoA)
e = AoA(i)
n = UBound(e)
ReDim Preserve e(n * 2 + 1)
For m = n + 1 To UBound(e)
e(m) = UCase(e(m - n - 1))
Next
AoA(i) = e ' replace whole element
WScript.Echo Join(AoA(i), "")
Next
output:
cscript 37951664.vbs
----- test data:
some
words
of
different
length
----- array assignment copies (For Each elem ... does not 'work'):
some
words
of
different
length
----- array assignment copies:
Some
sOme
Words
wOrds
Of
oF
Different
dIfferent
Length
lEngth
----- replace whole subarrays:
sOmeSOME
wOrdsWORDS
oFOF
dIfferentDIFFERENT
lEngthLENGTH
I have below sample data. I want to convert this string into an array
device_name="Text Data" d_id=7454579598 status="Active" Key=947-4378-43248274
I tried below:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
("d:\vbfile.txt", ForReading)
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
arrServiceList = Split(strNextLine , " ")
For i = 0 to Ubound(arrServiceList)
Wscript.Echo arrServiceList(i)
Next
Loop
it generates below
device_name="Text
Data"
d_id=7454579598
status="Active"
Key=947-4378-43248274
Expected output
device_name="Text Data"
d_id=7454579598
status="Active"
Key=947-4378-43248274
How about this approach:
Option Explicit
Const ForReading = 1
Dim FSO, keyValueExpr
Set FSO = CreateObject("Scripting.FileSystemObject")
Set keyValueExpr = New RegExp
keyValueExpr.Pattern = "\b(\w+)=(""[^""]*""|\S*)"
keyValueExpr.Global = True
Dim result, record, match
Set result = CreateObject("Scripting.Dictionary")
With FSO.OpenTextFile("D:\vbfile.txt", ForReading)
While Not .AtEndOfStream
Set record = CreateObject("Scripting.Dictionary")
result.Add result.Count + 1, record
For Each match In keyValueExpr.Execute(.ReadLine)
record.Add match.SubMatches(0), match.SubMatches(1)
Next
Wend
.Close
End With
Dim msg, lineNo, key
For Each lineNo In result
msg = "Line " & lineNo & vbNewLine
For Each key In result(lineNo)
msg = msg & vbNewLine & key & ": " & result(lineNo)(key)
Next
MsgBox msg
Next
It uses a regular expression that can identify key-value pairs that fulfill these conditions:
The key is a string of characters (a-z), digits (0-9) or underscores (_)
The value is anything that is either enclosed in double quotes or anything except a space.
Compare https://regex101.com/r/zL2mX5/1
The program creates nested dictionaries, the outer dictionary holding all lines of the file with the corresponding line numbers (1..n) for keys, each inner dictionary holds the key-value pairs found on each line.
This layout gives you the opportunity to address every value very conveniently:
value = result(3)("status")
Here is a function that might help. It takes a string and a delimiter and returns an array obtained by splitting on the delimiter -- whenever the delimiter isn't inside a quote:
Function SmartSplit(s, d)
Dim c, i, j, k, n, A, quoted
n = Len(s)
ReDim A(n - 1)
quoted = False
i = 1
k = 0
For j = 1 To n
c = Mid(s, j, 1)
If c = """" Then quoted = Not quoted
If c = d And Not quoted Then
A(k) = Mid(s, i, j - i)
k = k + 1
i = j + 1
End If
Next
If i < n Then
A(k) = Mid(s, i)
Else
k = k - 1
End If
ReDim Preserve A(k)
SmartSplit = A
End Function
In your example -- just replace Split by SmartSplit and it should work.
for the next "A to Z" getting results.
for into; 5 and the number 6, I want to add.
How do I make.
for k = asc("A") to asc("Z")
response.write chr(k)
next
Result :
A
B
C
..
Z
I want
A
B
C
..
Z
5
6
Such as (
k = asc("A") to asc("Z") add "5" and add"6" )
Thank You.
You can't really have a loop for this, just add separate commands:
for k = asc("A") to asc("Z")
response.write chr(k)
next
response.write "5"
response.write "6"
Another option is storing all the ASCII numbers in array then looping that array:
Dim arrLetters(), x
ReDim arrLetters(-1)
For k=Asc("A") To Asc("Z")
ReDim Preserve arrLetters(UBound(arrLetters) + 1)
arrLetters(UBound(arrLetters)) = k
Next
ReDim Preserve arrLetters(UBound(arrLetters) + 1)
arrLetters(UBound(arrLetters)) = Asc("5")
ReDim Preserve arrLetters(UBound(arrLetters) + 1)
arrLetters(UBound(arrLetters)) = Asc("6")
For x=0 To UBound(arrLetters)
k = arrLetters(x)
response.write chr(k)
Next
Erase arrLetters
strString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ56"
For i=1 To Len(strString)
Response.Write Mid(strString,i,1)
Next
dim a(100)
a(0)=9,a(1)=3,a(2)=-3,a(3)=8,a(4)=2
how can i find size of used array(i.e used size is 5
You have to count the non-empty elements:
Option Explicit
Function UsedElms(a)
UsedElms = 0
Dim i
For i = 0 To UBound(a)
If Not IsEmpty(a(i)) Then UsedElms = UsedElms + 1
Next
End Function
Dim a(5)
a(2) = 2
a(4) = 4
WScript.Echo "ub:", UBound(a), "sz:", UBound(a) + 1, "us:", UsedElms(a)
output:
cscript 23027576.vbs
ub: 5 sz: 6 us: 2
Here's a hacky one-liner that I just thought of. It essentially counts the number of empty elements by converting them to spaces and then trimming them off.
intLastIndex = UBound(a) - Len(Join(a, " ")) + Len(Trim(Join(a, " ")))
Just for fun! Don't go putting it into your production code. It would certainly be more efficient as a two-liner:
s = Join(a, " ")
intLastIndex = UBound(a) - Len(s) + Len(Trim(s))
Ekkehard has the proper answer here, though. This hack only works if your array is filled contiguously.