Can I Create an Array of Points Arrays in Visual Basic - arrays

Dim myPointsArray As New List(Of Point) creates an array that I can fill with a For Next loop but I have several separate arrays that I want to fill so it would be great if Dim myPointsArrays(20) as.... would work so that I don't have to Dim a points array for each of my separate arrays. Then I could fill them with a nested For Next loop.
This is me filling one array
For i = 1 To 6
myPointsArray.Add(New Point(Ox + HxPnt(4, i) / skale, Oy - HyPnt(4, i) / skale))
Next
Here Ox,Oy represent an origin, HxHyPnts are members of an array of points, skale is used to scale the global values to drawing with pixels.
Problem is that I need to draw lots of different polylines and polygons from dozens of arrays.

You can create nested lists (List(Of T) is not an Array):
Dim myPointsArray As New List(Of List(Of Point))
For i = 1 To 6
Dim innerList = new List(Of Point)
myPointsArray.Add(innerList)
For j = 1 to 10
innerList.Add(New Point(Ox + HxPnt(4, i) / skale, Oy - HyPnt(4, i) / skale))
Next
Next
To iterate again over these values use the following:
For Each list As List(Of Point) in myPointsArray
For Each p As Point in list
// Access p here
Next
Next

Got it!
I created a new points array variable (newPoints), filled it from the list then converted it with the .ToArray thingy. Then drew each polyline in the loop by filling, clearing and refilling the array. Is this the best way to do this. Seems good to me.
For Each list As List(Of Point) In myPointsArray
For Each p As Point In list
newPoints.Add(New Point((Ox + p.X) / skale, (Oy + p.Y) / skale))
Next
e.Graphics.DrawLines(myPen, newPoints.ToArray)
newPoints.Clear()
Next

Related

How do I remove all null or empty elements from my array in vb.net?

The code block computes two values for speeds; Vsf and Vro using their corresponding parameter values: Angle, Super-elevation and Radius for each iteration of the for- loop statement. During each loop, it selects the minimum of both speed values. In some scenario's, Angle, super-elevation but most of all, Radius are all null values, leading to Vsf and Vro values of null and hence Vmin of null. I want to eliminate these scenarios and produce just non-zero values for Vmin hence my question.
For i = 1 To CInt(txtNumSections.Text)
ReDim Preserve Vsf(i)
ReDim Preserve Vro(i)
ReDim Preserve Vmin(i)
Vsf(i) = (((0.91544 - 0.00166 * Angle(i) - 0.000002 * W - 0.054248 * Superelevation(i) - Sidefrictionfactor) / 0.013939) * Radius(i)) ^ 0.5
Vro(i) = (((1.05653 - 0.004861 * Angle(i) - 0.000004 * W - 0.314653 * Superelevation(i) - rolloverthreshold) / 0.012729) * Radius(i)) ^ 0.5
Vmin(i) = Math.Min(Vsf(i), Vro(i))
If Vmin(i) <= "0" Then
Vmin(i) = "0"
End If
Next
Dim myList = New List(Of Double)
For Each s In Vmin
If Not String.IsNullOrWhiteSpace(s) Then
myList.Add(s)
End If
Next
Vmin = myList.ToArray()
Since arrays are immutable(you can't add or remove items) you can just re-create it:
myArray = myArray.Where(Function(s) Not String.IsNullOrEmpty(s)).ToArray()
This is a String() but this LINQ query works similar with any other type of array.
A non-LINQ appproach would be to fill a List(of T) and then use ToArray:
Dim myList = New List(Of String)
For Each s In myArray
If Not String.IsNullOrEmpty(s)
myList.Add(s)
End If
Next
myArray = myList.ToArray()
You see that LINQ can make your code more readable and understandable.
Alright guys, I found a workaround this, based on the purpose of the code piece. I simply set all null or negative values to the maximum allowable values. There's some context to it which makes it a sensible approach but I would need to explain the entire operation of the code block which I'm not sure you would have any interest in. Anyway, thanks for your contributions. They are very much appreciated

Can you link an array variable with a control?

I am making a program with PictureBox controls. It would be easiest to manage the things I want to do with the PictureBox controls if they were in an array already.
This is what I have tried.
Sub drawtiles()
For x As Integer = 0 To 32 Step 1
For y As Integer = 0 To 24 Step 1
Dim tile As New PictureBox()
tile.Width = 20
tile.Height = 20
tile.Top = y * 20
tile.Left = x * 20
tile.BackColor = Color.CornflowerBlue
Dim r As Random = New Random
' Get random numbers between 1 and 3.
' ... The values 1 and 2 are possible.
Dim s As Integer = (r.Next(1, 3))
If s = 1 Then
tile.BackgroundImage = My.Resources.g1774
Else
tile.BackgroundImage = My.Resources.rect881
End If
tiles(x)(y) = tile
Controls.Add(tile)
Next
Next
End Sub
... with the array being made here
Public Class Form1
Public tiles As Array
So, how would I assign the Picturebox control, to the 3d array value?
You should almost never declare something as type Array. That is really only for when you want to be able to refer to an array of any type. That usually only happens with method parameters but, since the advent of generics, you can just write a generic method where the generic type parameter is the type of the array, e.g.
Private Sub ProcessArray(Of T)(array As T())
For i = 0 To array.GetUpperBound(0)
'Process element at index i here.
Next
End Sub
If you want an array of PictureBoxes then create a PictureBox array. Also, don't use a jagged array when you should be using a 2D array. This is a jagged array of PictureBoxes:
Private jaggedArrays As PictureBox()()
and this is a 2D array:
Private twoDimensionalArray As PictureBox(,)
The difference is that the second is a single object whereas the first is a 1D array containing multiple 1D arrays.
You should be creating the array like this:
Private tiles(32, 24) As PictureBox
And then populating it like this:
For i = 0 To tiles.GetUpperBound(0)
For j = 0 To tiles.GetUpperBound(1)
Dim tile As New PictureBox
'...
tiles(i, j) = tile
Next
Next
Never ever ever use Array as a type name in VB.Net. Instead, you would declare it like this:
Public tiles() As PictureBox
Or this:
Public tiles(32*24) As PictureBox
Or this (probably your best fit):
Public tiles(32, 24) As PictureBox
Or this:
Public tiles As New List(Of PictureBox)
Or skip the extra array altogether, put the controls inside a Panel or GroupBox container, and write code like this when you need to find them:
For Each tile As Picturebox in TilePanel.Controls.OfType(Of PictureBox)()
' ...
Next
Remember, with the move to the .Net ecosystem, VB now works so much better when things are strongly-typed. Option Strict really should be On, and you want very specific type names.

Combining items within an array in VB.NET

I'm very new to VB.net and I have an array, like so,
points = [[1,2],[5,6],[7,8],[9,10]]
The result I want is to be able to break this up into pairs, starting with the first item and then combining it with the next item, until the last item is paired with the previous item, like so:
new points = [[[1,2],[5,6]],[[5,6],[7,8]],[[7,8],[9,10]]]
Doing it without a loop is preferred. Being a python guy, i would do this using a list comprehension with array slicing, I'm interested to see how it would look like in VB.
thanks for your help.
One option would be:
Dim pointPairs = Enumerable.Range(0, points.Length - 2).Select(Function(n) Tuple.Create(points(n), points(n + 1)))
That will give you an IEnumerable(Of Tuple(Of Point, Point)). You could then enumerate that directly or call ToArray or ToList, e.g.
Dim pointPairs = Enumerable.Range(0, points.Length - 2).
Select(Function(n) Tuple.Create(points(n), points(n + 1))).
ToArray()

Filling a 3D array with 2D arrays in VBA

I have a set of data where each item has a 2D array of information corresponding to it. I'd like to create a 3D array where the first dimension is the item name and the second and third dimensions are taken up by the info corresponding to the item.
I can read the data for each item into a 2D array, but I can't figure out how to get the 2D array read into the 3D array.
I know the sizes of all the dimensions so I can create an array of fixed size before I begin the reading and writing process.
I'd like to do this by looping only through the names of the items and not looping through every cell of every 2D array.
It is easy to get the 2D arrays read in to an ArrayList but I want to be able to name the items and be able to read these back in to excel and it seems difficult to do with an ArrayList.
The question is: how do I read a 2D selection from excel into a 3D fixed sized array in VBA?
Here is an example of each approach: array of arrays or Dictionary of arrays. The Dictionary approach is considerably easier than the array of arrays if what you want is keyed lookup of values. There might be merits to the array of arrays in other cases.
This is dummy code with no real purpose but to show a couple things: grabbing a single value and an array of values. I am building a 2D array of values by grabbing some Range data which is easy and 2D. From there I build up the arrays of these values and then put them into the relevant data structure. Then I poke at the data structure to get some values out of it.
Array of Arrays approach is shown first (and outputs on the left of the picture).
Sub ArraysOfArrays()
Dim arrA() As Variant
Dim arrB() As Variant
'wire up a 2-D array
arrA = Range("B2:D4").Value
arrB = Range("F2:H4").Value
Dim arrCombo() As Variant
ReDim arrCombo(2, 1) As Variant
'name and give data
arrCombo(0, 0) = "arrA"
arrCombo(1, 0) = arrA
'add more elements
ReDim Preserve arrCombo(2, 2)
arrCombo(0, 1) = "arrB"
arrCombo(1, 1) = arrB
'output a single result
'cell(2,2) of arrA
Range("B6") = arrCombo(1, 0)(2, 2)
Dim str_search As String
str_search = "arrB"
'iterate through and output arrB to cells
Dim i As Integer
For i = LBound(arrCombo, 1) To UBound(arrCombo, 1)
If arrCombo(0, i) = str_search Then
Range("B8").Resize(3, 3).Value = arrCombo(1, i)
End If
Next i
End Sub
Couple key points here:
You can only expand the array using ReDim. ReDim is very particular that you only change the last dimension of the array when used with Preserve. Since I need one of them to track the number of entries, I do that in the second index which is... unnatural. If you know the size in advance, this painful step is skipped.
My final array is a 2xN array where the 2 contains a name and a YxZ array of data.
In order to find a given array in the mix, you have to iterate through them all.
Dictionary of Arrays is far less code and more elegant. Be sure to add the reference Tools->References in the VBA editor to Microsoft Scripting Runtime.
Sub DictionaryOfArrays()
Dim dict As New Scripting.Dictionary
'wire up a 2-D array
arrA = Range("B2:D4").Value
arrB = Range("F2:H4").Value
dict.Add "arrA", arrA
dict.Add "arrB", arrB
'get a single value
Range("F6") = dict("arrB")(2, 2)
'get a array of values
Range("F8").Resize(3, 3) = dict("arrA")
End Sub
Picture of input data and results
Data to copy if you want it (paste in B1)
a b
1 2 3 10 11 12
4 5 6 13 14 15
7 8 9 16 17 18

How to iterate an array of a dynamic size in a loop

I am using VB.NET.
I would like have an array called A1 and I will perform for loop inside that array.
In the middle of the for loop, I need to remove an item from that A1 array.
I am aware that if I remove that object from A1 array, the program will crash (out of bounds error message).
Which array variable in VB.NET would allow me to perform the task above?
Code sample is most welcomed!
Thank you.
The easiest way would be to use a list instead of an array (or convert the array you have to a List(of T).
The trick then is to move from the end of the list to the front instead of the other way around.
For example:
Sub Main()
Dim RndGenerator as New Random
Dim a As New List(Of Double)
For i = 0 To 99
a.Add(RndGenerator.NextDouble() * 10) 'Populate the list
Next
For i = a.Count - 1 To 0 Step -1 'This loop performs the deletion.
If a(i) > 5 Then a.RemoveAt(i)
Next
Console.ReadKey() 'Or debugger.Break to look at the result
End Sub
This will populate a list with random numbers from 0 to 10. It then removes all numbers >5 from the list.
Edit:
Good point from Steven Doggart on not using VB6 Relics. Edited the code to use the System.Random class instead.

Resources