I'm trying to remove an element from an integer array given its index, are there any simple ways of accomplishing just that in VB.Net?
All I can find is .RemoveAt() for removing a string in an ArrayList, but none for an integer in an integer array.
Dim PossibleValues(8) As Integer
For x As Integer = 0 To 8
PossibleValues(x) = x + 1
Next
Added the code, don't think it entails much as I am now trying to find ways to remove an element from the array PossibleValues
The problem with removing an item from an array is that it is of fixed size. So The simplest way is to convert the array to a list, ToList(), and then do the RemoveAt and then, if you need to, convert it back to a new array with ToArray().
EDIT
Dim PossibleValues(8) As Integer
For x As Integer = 0 To 8
PossibleValues(x) = x + 1
Next
Dim tempList = PossibleValues.ToList()
tempList.RemoveAt(1)
PossibleValues = tempList.ToArray()
Related
This is a tricky one for me to explain, so I'll start with the code I have so far, and later with what I am trying to achieve.
Current Code
Option Explicit
Public eSigTickerArr As Variant
' Public type to save array
Type Watchlist
eSigTicker As String
Op As Double
Hi As Double
Lo As Double
Cl As Double
Vol As Double
BarTime As Variant
End Type
Public WatchlistArr() As Watchlist ' save an array of special type "Watchlist"
'====================================================================
Sub Mainr()
ReDim WatchlistArr(0) ' init array size
eSigTickerArr = Array("Part1", "Part2", "Part3")
For Each eSigTickerElem In eSigTickerArr
' check if first member of array is occupied
If WatchlistArr(0).eSigTicker <> "" Then ' not first time running this code >> increase array size by 1
ReDim Preserve WatchlistArr(UBound(WatchlistArr) + 1) ' increase array size by 1
End If
' ... Some Code, working fine ....
' populate array Type with data (also works)
With WatchlistArr(UBound(WatchlistArr))
.eSigTicker = eSigTickerElem
.Op = LastCSVLine(2)
.Hi = LastCSVLine(3)
.Lo = LastCSVLine(4)
.Cl = LastCSVLine(5)
.Vol = LastCSVLine(6)
.BarTime = LastCSVLine(1)
End With
Next eSigTickerElem
' ******* calculate the average of only "Hi" ******
Dim myAvg
myAvg = WorksheetFunction.Average(WatchlistArr.Hi) '<--- Getting an Error !
End Sub
I'm getting an error at the line above.
My Challenge: I want to get the average only of a certain variable of my type array WatchlistArr, and I don't want to use a loop, as there can be 10,000 records (or more).
Is there any way to get the value with the Average function ?
Should I switch to 2-D array ? or Maybe 3-D array ?
myAvg = WorksheetFunction.Average(WatchlistArr.Hi) '<--- Getting an Error !
Yep. What this code means to do is similar to this:
myAvg = watchListArr.Select(item => item.Hi).Average();
Where item => item.Hi is a selector function that is invoked for every item in watchListArr. The only problem is that this is LINQ / C#, not VBA. VBA doesn't support delegates and other funky stuff even C# couldn't dream to do in v1.0.
But VBA has control flow structures that let you perform an action for every item in an array: use a For loop!
Dim i As Long, total As Double, count As Long
For i = LBound(watchListArr) To UBound(watchListArr)
total = total + watchListArr(i).Hi
If watchListArr(i).Hi <> 0 Then count = count + 1 'assuming zeroes are excluded
Next i
If count <> 0 Then myAvg = total / count
If you want to use Application.WorksheetFunction.Average, you'll need to copy the Hi member of every item in your array into its own array, and give it that array - and that will require... a loop... which is wasted cycles if that loop isn't also computing the average as it goes.
As long as you're not using a For Each loop to iterate the array, you'll do fine. Iterating a 30K items array with a For loop is pretty much instant, no worries there.
You could define WatchlistArr as a 2-D array and then try this logic:
Dim myArray As Variant
myArray = Application.WorksheetFunction.Index(WatchlistArr, 0, 2)
This will return column 2 as as array, which can be passed into the Average method:
myAvg = WorksheetFunction.Average(myArray)
I am kinda new in VB.net; pretty much what I have been looking for is a way to calculate the similarity of a byte array. I have been able to determine whether they are equal or not, but I haven't figured out how to calculate how similar they are in percentage. Any idea is appreciated. Thanks! Leo.
The following function takes two Byte arrays as its arguments. If the arrays are not the same length, it throws an exception. Otherwise, it returns the fraction of the elements in one array that are equal to the element at the same position in the other array.
Function PercentAlike(array1() As Byte, array2() As Byte) As Double
If array1.Length <> array2.Length Then Throw New ArgumentException("Arrays must have the same length")
Dim same As Integer
For i As Integer = 0 To array1.Length - 1
If array1(i) = array2(i) Then same += 1
Next
Return same / array1.Length
End Function
[Added in response to the comment that the arrays may not be the same length]
If you need to calculate a percentage even if the arrays are of different lengths, you can use the following function. It returns the number of elements in one array that are equal to the element at the same position in the other array (ignoring the extra elements in the longer array) as a fraction of the number of elements in the longer array.
Function PercentAlike(array1() As Byte, array2() As Byte) As Double
Dim same As Integer
For i As Integer = 0 To Math.Min(array1.Length, array2.Length) - 1
If array1(i) = array2(i) Then same += 1
Next
Return same / Math.Max(array1.Length, array2.Length)
End Function
I am trying to get the index of the item in an array VBA, but I have issue getting it.
Const NoOfVol As Integer = 5
Dim vol(NoOfVol) As Integer
For Index = 1 To NoOfVol
vol(Index) = Cells(15 + Index, 8).Value
Next
The array looks like this: (-2500,-1250,0,1250,2500). I am calling the function this way.
Function Find(ByVal Value As Variant, arr As Variant) As Integer
Find = Application.Match(Value, arr, False)
End Function
posOfVol = Find(-1250, vol)
But the posOfVol = 3, when it should be 2. Not sure where my error is. Need some guidance on this.
Your array is actually effectively declared as:
Dim vol(0 to NoOfVol) As Integer
unless you have an Option Base 1 statement. Since your loop goes from 1 to 5, you never populate the first element of the array and it retains its default value of 0. Therefore your array is actually:
(0,-2500,-1250,0,1250,2500)
and since you are looking for an exact match, -1250 is found at the third position.
I have 3 one dimensional arrays.
Each contains information that corresponds to the other 2 arrays.
e.g Array 1 contains a customer first name
Array 2 contains a customer last name
Array 3 contains the customer phone number.
This is not my actual example but is easiest to explain.
How do I sort all three arrays so that they are sorted in order by say customer last name.
If Mr Smith is sorted and has moved from position 10 to position 5 in the lastname array, I would expect his phone number and first name to also be in position 5 in the respective arrays.
I am dealing with arrays with 10,000's of items so I would like to avoid looping (my current method) as this is incredibly slow.
Hoping to use the array.sort methods.
Can someone help me?
Ok - So I have tried to use a new data Type but am still at a loss how I can instantly filter using this. Below is my sample code which has a couple of issues. If someone can resolve - it would love to learn how you did it.
The purpose of the code is to return an array containing grouped issues.
For simplicity I have assumed in the example that each constant found is an issue.
If an issue is found, combine it with other issues found on that same worksheet.
e.g The number 2 is found in both cells A1 and A2 on sheet 1. The array should return A1:A2.
If the issues are found in A1 on sheet 1 and A2 in sheet 2, two seperate array entries would be returned.
Test File and Code Here
Public Type Issues
ws_Sheet As Integer
rng_Range As String
s_Formula As String
s_Combined As String
d_ItemCount As Double
End Type
Sub IssuesFound()
Dim MyIssues() As Issues
Dim i_SheetCount As Integer
Dim s_Formula As String
Dim rng_Range As Range
Dim d_IssueCounter As Double
Dim s_SearchFor As String
Dim a_TempArray() As Issues
Dim d_InsertCounter As Double
d_IssueCounter = -1
' Loop All Sheets Using A Counter Rather Than For Each
For i_SheetCount = 1 To ActiveWorkbook.Sheets.Count
' Loop all Constants On Worksheet
For Each rng_Range In Sheets(i_SheetCount).Cells.SpecialCells(xlCellTypeConstants, 23)
If d_IssueCounter = -1 Then
' First Time and Issue Is Found, Start Recording In An Array
d_IssueCounter = d_IssueCounter + 1
ReDim MyIssues(0)
MyIssues(0).ws_Sheet = i_SheetCount
MyIssues(0).rng_Range = rng_Range.AddressLocal
MyIssues(0).s_Formula = rng_Range.Value
MyIssues(0).s_Combined = i_SheetCount & "#" & rng_Range.Value
MyIssues(0).d_ItemCount = 0
Else
' Going To Look For Issues Found On The Same Sheet with The Same Constant Value
s_SearchFor = i_SheetCount & "#" & rng_Range.Value
' HELP HERE: Need To Ideally Return Whether The Above Search Term Exists In The Array
' Without looping, and I want to return the position in the array if the item is found
a_TempArray = MyIssues 'Filter(MyIssues.s_Combined, s_SearchFor, True, vbTextCompare)
If IsVarArrayEmpty(a_TempArray) = True Then
' New Issue Found - Increase Counter By + 1
d_IssueCounter = d_IssueCounter + 1
' Increase The Array By 1
ReDim Preserve MyIssues(d_IssueCounter)
' Record The Information About The Constant Found. Sheet Number, Constant, Range, and also a combined string for searching and the array position
MyIssues(0).ws_Sheet = i_SheetCount
MyIssues(0).rng_Range = rng_Range.AddressLocal
MyIssues(0).s_Formula = rng_Range.Value
MyIssues(0).s_Combined = i_SheetCount & "#" & rng_Range.Value
MyIssues(0).d_ItemCount = 0
Else
' Get The Array Position Where Other Issues With The Same Worksheet and Constant are Stored
d_InsertCounter = a_TempArray.d_ItemCount
' Add The New Found Constant To The Range Already Containing The Same Constants on This Worksheet
MyIssues(d_InsertCounter).rng_Range = Union(rng_Range, Range(MyIssues(d_InsertCounter).rng_Range)).AddressLocal
End If
End If
Next
Next
End Sub
Function IsVarArrayEmpty(ByRef anArray As Issues)
Dim i As Integer
On Error Resume Next
i = UBound(anArray, 1)
If Err.Number = 0 Then
IsVarArrayEmpty = False
Else
IsVarArrayEmpty = True
End If
End Function
Sample Test File and Code Here
As suggested, you should not be using concurrent arrays at all. You should be defining a type with three properties and then creating a single array or collection of that type.
To answer your question though, there is no way to sort three arrays in concert but there is a way to sort two. What that means is that you can create a copy of the array that you want to use as keys and then use the copy to sort one of the other arrays and the original to sort the other. Check out the documentation for the Array.Copy overload that takes two arrays as arguments.
That said, copying the array and then sorting twice is a big overhead so you may not gain much, if anything, from this method. Better to just do it the right way in the first place, i.e. use a single array of a complex type rather than concurrent arrays of simple types. It's not 1960 any more, after all.
I have a string array called hexsub, each "instance" of the array holds 2 characters. I made a new array called finalhex, i wanted that each "instance" of the new array held 2 of the previous, so: hexsub(0)=06, hexsub(1)=AF, then finalhex(0)=06AF. How can i do this?
The join function will join all the elements of the array regardless of how many there are within reason of course.
finalhex(0) = Join(hexsub,"")
or to split them up in pairs, something like this might work:
For I = 0 to hexsub.Count-1 Step 2
finalhex(I/2) = hexsub(I).Trim + hexsub(I+1).Trim
Next
Now each element of finalhex will contain 2 concatenated elements of hexsub
'assuming an even number of array elements
Dim NumberOfCombinedElements as Integer = hexsub.count / 2
Dim FinalHex(NumberOfCombinedElements ) as string
for I as integer = 0 to NumberOfCombinedElements - 1
finalhex(I) = hexsub(I*2) & hexsub(I*2 + 1)
next