How many dimensions in my array or get the last one - arrays

How can I find out the number of dimensions in an array in Classic ASP ( VBScript ) .
I am being passed an Array with multiple dimensions but I only want to look at the last. Seems easy in other languages.

Ubound(MySingleDimensionalArray, 2) ' Number of Array Elements
Ubound(MyMultiDimensionalArray, 1) ' Number of Columns
Ubound(MyMultiDimensionalArray, 2) ' Number of Rows

Similar approach to feihtthief's answer here as I assume this is what you want rather than the size of a specified dimension.
Function NumDimensions(arr)
Dim dimensions : dimensions = 0
On Error Resume Next
Do While Err.number = 0
dimensions = dimensions + 1
UBound arr, dimensions
Loop
On Error Goto 0
NumDimensions = dimensions - 1
End Function
Then calling it as so:
Dim test(9, 5, 4, 3, 9, 1, 3, 5)
NumDimensions(test)
will give you the value 8
It's a bit crappy but it'll do what you asked.

function ArrayDimensions( theArray )
dim Result,test
Result = 0
if isarray(theArray) then
on error resume next
do
test = -2
test = ubound(theArray,result+1)
if test > -2 then result = result + 1
loop until test=-2
on error goto 0
end if
ArrayDimensions = Result
end function

Related

VBA: Return the closest value using a 1-Dimensional Array

I am using the WorksheetFunction.Large and WorksheetFunction.CountIf commands to determine the closest "jaw size" using a 1-Dimensional array as the source data, shown below.
wsSheet.Range("H2").Value = WorksheetFunction.Large(myArray, WorksheetFunction.CountIf(myArray, ">" & SizePush) + 1)
The problem I am having is when I use whole numbers (1, 2, 3, 4) the resulting jaw size does not take the closest value from the array, it takes the second closest value. The array I am using is shown in image 1 (myArray), and 'SizePush' refers to the following equation: (Start Diameter - (Start Diameter - End Diameter))-0.05.
a snippet of the jaw size array
I have attached the code that I am using. If anyone can help that would be greatly appreciated because I cannot figure out why only whole numbers cause an issue.
Dim StartDiam, EndDiam, PReduction, Push1, Push2, Push3, Push4, SizePush
StartDiam = 0.5
EndDiam = 4.75
PReduction = Worksheets("Sheet1").Range("D2").Value
Push1 = Worksheets("Sheet1").Range("I2").Value
Push2 = Worksheets("Sheet1").Range("I3").Value
Push3 = Worksheets("Sheet1").Range("I4").Value
Push4 = Worksheets("Sheet1").Range("I5").Value
SizePush = Worksheets("Sheet1").Range("I6").Value
Dim myArray
Set myArray = Range("T2:T51")
Dim wsSheet As Worksheet
Set wsSheet = Worksheets("Sheet1")
If StartDiam < wsSheet.Range("B2").Value Then
If EndDiam > wsSheet.Range("C2").Value Then
'size of jaw if the push is one
If wsSheet.Range("I2").Value = Push1 Then
wsSheet.Range("H2").Value = WorksheetFunction.Large(myArray, WorksheetFunction.CountIf(myArray, ">" & SizePush) + 1)
Exit Sub
End If

How can I find the nonzero values in a MATLAB cells array?

The following code generates an cell array Index [1x29], where each cell is an array [29x6]:
for i = 1 : size(P1_cell,1)
for j = 1 : size(P1_cell,2)
[Lia,Lib] = ismember(P1_cell{i,j},PATTERNS_FOR_ERANOS_cell{1},'rows');
Index1(i,j) = Lib % 29x6
end
Index{i} = Index1; % 1x29
end
How can I find the nonzero values in Index array?, i.e. generate an array with the number of non-zero values in each row of the Index1 array. I tried the following loop, but it doesn't work, it creates conflict with the previous one:
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros = length(find(Index{:,i}(j,:))); %% I just need the length of the find function output
end
end
I need help, Thanks in advance.
The nnz() (number of non-zeros) function can be used to evaluate the number of non-zero elements. To obtain the specific positive values you can index the array by using the indices returned by the find() function. I used some random test data but it should work for 29 by 6 sized arrays as well.
%Random test data%
Index{1} = [5 2 3 0 zeros(1,25)];
Index{2} = [9 2 3 1 zeros(1,25)];
Index{3} = [5 5 5 5 zeros(1,25)];
%Initializing and array to count the number of zeroes%
Non_Zero_Counts = zeros(length(Index),1);
for Row_Index = 1: length(Index)
%Evaluating the number of positive values%
Array = Index{Row_Index};
Non_Zero_Counts(Row_Index) = nnz(Array);
%Retrieving the positive values%
Positive_Indices = find(Array);
PositiveElements{Row_Index} = Array(Positive_Indices);
disp(Non_Zero_Counts(Row_Index) + " Non-Zero Elements ");
disp(PositiveElements{Row_Index});
end
Ran using MATLAB R2019b
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros(i,j) = nnz(Index{:,i}(j,:));
end
end

Comparing arrays with numbers in vb.net

I need a way to compare two arrays in vb.net and save result in third array:
Dim KonRes(3) As Integer
Dim UserRes(3) As Integer
Dim YelRed(3) As Integer
KonRes(0) = 1
KonRes(1) = 2
KonRes(2) = 3
KonRes(3) = 4
UserRes(0) = 4
UserRes(1) = 3
UserRes(2) = 2
UserRes(3) = 1
How to compare those arrays so in declared variable YelRed I should have results like this:
If UserRes(0) = KonRes(0) Then
YelRed(0) = 2
If UserRes(0) = KonRes(1 or 2 or 3) Then
YelRed(0) = 1
If UserRes(0) does not contain any number like in KonRes then YelRed(0) should be 0. Also it should not make duplicate results, in other words if it already checked UserRes(0) = KonRes(0) then it should not check KonRes(0) in next check. It's not a problem to compare if those arrays are completely same, my problem is comparing each value of one array with other one, and collect results. Any suggestions?
There are a few basic ways of checking for a value in an integer array. The first is to manually search by looping through each value in the array, which may be what you want if you need to do complicated comparisons.
Second is the .Contains() method. It is simpler to use but will only give you a Boolean indicating whether the value is in the array or not. Example:
If KonRes.Contains(UserRes(0)) Then YelRed(0) = 1
Lastly, there's the IndexOf() function. It searches for a match and returns the index of a match if found, or one below the lower bound of the array if not (-1 for typical 0-based arrays). As I understand your needs from your comments above, this code should do the trick:
For i As Integer = 0 To 3
Select Case IndexOf(KonRes, UserRes(i))
Case i 'Matching postion
YelRed(i) = 2
Case -1 'No match found
YelRed(i) = 0
Case Else 'Match found at another position
YelRed(i) = 1
End Select
Next i
EDIT: I misunderstood the qualification about duplicates until #Sastreen clarified it. Here's a rewrite tailored to not count the same index as a match twice:
Dim processed(3) As Boolean
For i As Integer = 0 To 3
YelRed(i) = 0
If KonRes(i) = UserRes(i) And Not processed(i) Then
processed(i) = True
YelRed(i) = 2
Else
For j As Integer = 0 To 3
If KonRes(j) = UserRes(i) Then
processed(j) = True
YelRed(i) = 1
Exit For
End If
Next j
End If
Next i
If UserRes(0) = KonRes(0) that mean they are in same position in two
arrays, then YelRed(0) = 2, if UserRes(0) = KonRes(1,2,3) so number is
there and but not in same position, so YelRed(0) =1 and if the number
is not in second array it must be 0.
Use a For-Loop:
For i As Int32 = 0 To KonRes.Length - 1
If KonRes(i) = UserRes(i) Then
' Same position '
YelRed(i) = 2
ElseIf UserRes.Contains(KonRes(i)) Then
' Other position '
YelRed(i) = 1
Else
' Not contained '
YelRed(i) = 0
End If
Next
You can use nested For loops to go through the two arrays to compare, and then use Exit For to leave at any time.
The indicesToIgnore is for making sure it does not "make duplicate results" (this is harder to achieve with the IndexOf and contains methods).
Also it should not make duplicate results, in other words if it already checked UserRes(0) = KonRes(0) then it should not check KonRes(0) in next check.
Dim indicesToIgnore as New List(Of Integer)
'go through first array
For i as Integer = 0 to UserRes.length - 1 Step 1
'go through second array
For j as Integer = 0 to KonRes.length- 1 Step 1
'if the values are equal, check whether same index, then exit for
If (Not indicesToIgnore.contains(j) AndAlso UserRes(i) = KonRes(j)) Then
If i=j Then
YelRed(i) = 2
indicesToIgnore.add(j)
Else
YelRed(i) = 1
End If
Exit For
End If
Next
Next
You don't need to set YelRed(i) to 0 at any time because it defaults as this. You just need to make sure YelRed has the same size as the other arrays.
If you also want it to not look at the KonRes value (for duplicates) if it contains it at a different index, simply add indicesToIgnore.add(j) at the end of the Else (after YelRed(i) = 1) as well.
I think this will do the job, if KonRes(0) = UserRes(0) then YelRed(0) = 1 else YelRed(0) = 2
Dim KonRes(3) As Integer
Dim UserRes(3) As Integer
Dim YelRed(3) As Integer
KonRes(0) = 1
KonRes(1) = 2
KonRes(2) = 3
KonRes(3) = 4
UserRes(0) = 4
UserRes(1) = 2
UserRes(2) = 2
UserRes(3) = 1
Dim Uindex As Integer = 0
For Each item In UserRes
Dim Kindex As Integer = 0
For Each i In KonRes
If item = i Then
If Kindex = Uindex Then
YelRed(Uindex) = 1
Else
YelRed(Uindex) = 2
End If
End If
Kindex += 1
Next
Uindex += 1
Next
You didn't told us what the output should be. It's a bit confusing. In my case, it will be {1, 1, 0, 0}. If was to be done with 2 for loop. On that loops everything in KonRes while the other only loop what wasn't checked yet in UserRes.
For k As Integer = 0 To KonRes.Length - 1
If KonRes(k) = UserRes(k) Then
YelRed(k) = 2
Else
YelRed(k) = 0
For u As Integer = k + 1 To UserRes.Length - 1
If KonRes(k) = UserRes(u) Then
YelRed(k) = 1
Exit For
End If
Next
End If
Next
You could use the comparison from the array.
Dim iNextActivityTypeCd As Integer = 18400
Dim activities() As Integer = {1,18400, 2300, 3423}
If activities.Contains(iNextActivityTypeCd) Then
Dim foo = 1
End If

Creating arrays in QTP

I am trying to create an array of integers in QTP ( the ints are 9, 16, 25,34,43). I think the code to instantiate it should be (but I could be wrong since I have never created an array in QTP before),
Dim pages(5)
pages(0) = 9
pages(1) = 16
...
Then I have a for loop with a variable that goes from 1 to 50 and based off of the value of the variable it does one thing and if the variable is one of the values in the array it does something else. For that I have,
For g = 1 to 50
if g<> 9 and g<> 16 and g<> 25 and g<>34 and g<> 43 Then
DoCoolStuff...
else
DoBoringStuff...
End If
Next
My question is, is there a command that will allow me to replace that ugly if statement with something like
if g <> in pages*?
If you want a Dimensioned Array, then that is the only way to declare an array. If you wanted a Non dimensioned array you then can use,
Dim pages()
pages = Array(9, 16, 25, 34, 43)
However, you can also do this,
Dim pages()
ReDim pages(5)
pages = Array(9, 16, 25, 34, 43)
Coming to your problem, you can get this going by using the Filter function. Although there is a very small problem. Filter method takes in String, so even with that function your will match 1, 2, 3, 4, 5, 6 along with the real/actual values 9, 16, 25, 34, 43.
As,
1 occurs in 16.
2 occurs in 25.
3 occurs in 34 and 43.
4occurs in 34 and 43.
5 occurs in 25.
6 occurs in 16.
It still thinks they occur in the String. One way to get around this is to Format the numbers as a two literal. Something like.
Dim pages(), g As Integer
ReDim pages(5)
pages = Array("09", "16", "25", "34", "43")
For g = 1 To 50
If UBound(Filter(pages, Format(g, "00"))) > -1 Then
'Do Cool Stuff here
Else
'Do Boring Stuff here
End If
Next
EDIT :
The other way is to create a User Defined Function that could Loop through your Array and find if the Value is Found in your Array. Something like,
Public Function FindArrayElement(SearchArray As Variant, LookupValue As Integer) As Boolean
Dim aCtr As Integer
For aCtr = 0 To UBound(SearchArray)
If CLng(SearchArray(aCtr)) = LookupValue Then
FindArrayElement = True
Exit Function
End If
Next
FindArrayElement = False
End Function
The function takes in two Arguments. The first is the Array in which the values are defined, the second is the Value looked up for. So your Original code would change to.
Dim pages(), g As Integer
ReDim pages(5)
pages = Array(9, 16, 25, 34, 43)
For g = 1 To 50
If FindArrayElement(pages, g) Then
'Do Cool Stuff here
Else
'Do Boring Stuff here
End If
Next
First, I, too, would suggest to initialize Pages like this:
Dim Pages(): Pages=(9,16,25,34,43)
Second, and independently from the first aspect, you could use this code to check if g is contained in Pages:
Dim Elem
Dim Found: Found=false
For Each Elem in Pages
If Elem = g then
Found=true
Exit For
End If
End For
If Found then
DoBoringStuff
else
DoCoolStuff
End If
The For..Each loop iterates as many times as there are elements in the Pages array. For each iteration, Elem is set to one Pages array element.
Note that the comparison is between Integers, as requested.

Matrix Math with VBA (System of Linear Equations)

I'm looking for a little help performing some matrix mathematics in Excel's VBA. I've read a ton of replies that suggest using the Excel worksheet but I'm hoping to solve this within the VBA code itself.
Although my application is much larger, let's say I have a system of linear equations that I need to solve:
x1 + x2 = 8
2*x1 + 4*x2 = 100
This can be solved with the simple matrix formula A*x = B or x = A^(-1) * B where,
A = [1, 1; 2, 4]
B = [8; 100]
If you solve this, you'll find x1 = -34 and x2 = 42. In terms of the matrix, then:
X = [-34; 42]
Using Excel's worksheets alongside its MMULT and MINVERSE functions makes this easy and I've gotten it to work just fine. My problem is I'm needing to do this calculation inside a VBA function. Here's what I'm trying:
Dim A(0 To 1, 0 To 1) As Single
Dim B(0 To 0, 0 To 1) As Single
Dim X(0 To 0, 0 To 1) As Single
A(0, 0) = 1
A(1, 0) = 1
A(0, 1) = 2
A(1, 1) = 4
B(0, 0) = 8
B(0, 1) = 100
X = Application.WorksheetFunction.MMult(Application.WorksheetFunction.MInverse(A), B)
Unfortunately, the last line yields a "Compile error: can't assign to array" message. I think it's because I have to specify each element of the array one at a time, but the worksheet functions are array functions.
How do I fix this?
Two things:
The same rule applies as in actual mathematics: B must be a vertical array for matrix multiplication to be possible in your case. Declare it as
Dim B(0 To 1, 0 To 0) As Single
and initialize it accordingly. Also, just declare
Dim X As Variant
since the MMult returns a Variant array. This is what was causing your original error.

Resources