Question 2D Array of string into custom type array

Zexor

Well-known member
Joined
Nov 28, 2008
Messages
520
Programming Experience
3-5
Can these 2 for loops be combine into one function where you input the 2DArray and the type to convert into, and it output an array of the customTypes?

VB.NET:
Private Class sCustomType
        Public Property A As String
        Public Property B As String
End Class
Private Class tCustomType
        Public Property C As String
        Public Property D As String
        Public Property E As String
End Class

Dim sArray(,) as string 
dim s() as sCustomType
Dim tArray(,) as string 
dim t() as tCustomType
.
.
For i As Integer = 0 To sArray.GetUpperBound(1)
   ReDim Preserve s(i)
   s(i) = New sCustomType
   With s(i)
        .A = sArray(0, i)
        .B = sArray(1, i)
   End With
Next
For i As Integer = 0 To tArray.GetUpperBound(1)
   ReDim Preserve t(i)
   t(i) = New tCustomType
   With t(i)
        .C = tArray(0, i)
        .D = tArray(1, i)
        .E = tArray(2, i)
   End With

Next

I am guessing it be something like this but how do you pass different custom type on a variable? and how do u go thru each item of the custom type and fill in the correct value?

VB.NET:
Dim sArray(,) as string 
dim s() as sCustomType
Dim tArray(,) as string 
dim t() as tCustomType
.
.

s=directcast(twoDArrayToObjectArray(sArray, sCustomType),sCustomType)
t=directcast(twoDArrayToObjectArray(tArray, tCustomType),tCustomType)
 

Private Function twoDArrayToObjectArray(twoDArray(,) As String, customType As Type) As Object()
        Dim output() As customType  'not sure how to pass different custom types
        For i As Integer = 0 To twoDArray.GetUpperBound(1)
            ReDim Preserve output(i)
            output(i) = New customType
            dim J as integer =0
            For Each item In output(i) ' not sure how to go thru each item
                item() = twoDArray(j, i)
                j+=1
            Next
        Next
        return output
End Function
 
Last edited:
First things first, why are you using ReDim Preserve? If you have a 2D array containing the original data then you know from that exactly what size the output array needs to be, so create it that size to begin with.

As for the question, the loops can be combined if the two output arrays will be the same size, i.e. the upper bound of rank 1 in the two 2D arrays is the same. If not then you need two separate loops because you have two separate sets of limits. You could put an If statement inside a single loop but that would be quite hacky. There's no advantage to that as it makes the code uglier and provides no boost to performance. For loops themselves are quick. It's the contents of the loop that takes the time, so you won't really improve time by putting two tasks in one loop instead of one task each in two loops. The time you loose by adding the conditional logic required would be more than the time you gain.
 
I want to create a function that does the conversion from a 2darray of string to an array of a custom type with different number of sub items. so i can just put in a 2darray and its matching custom type, out comes the array in that type.

And i am using redim preserve is because the amount of data changes. Only the 1st dimension is fix for a particular array. i am redimming the new arrays' 1st dimension which is the 2dArray's 2nd dimension.

What i was asking is. Can you pass a type to a function. And how to iterate thru each property in a custom type without actually typing the property names.
 
Last edited:
Hi,

Does this give you an example of the answer you are looking for?

VB.NET:
Public Class Form1
 
  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim my2DArray(,) As String = {{"Ian", "Ryder"}, {"Bill", "Pearson"}}
    Dim myConvertedArray As New ArrayList
 
    myConvertedArray = ConvertArray(my2DArray)
    For Each convName As myNameClass In myConvertedArray
      MsgBox(convName.FirstName & " " & convName.LastName)
    Next
  End Sub
 
  Private Function ConvertArray(my2DArray(,) As String) As ArrayList
    Dim myArrayList As New ArrayList
    Dim Counter As Integer
 
    For Counter = 0 To my2DArray.GetUpperBound(0)
      Dim myConvertedArray As New myNameClass
      With myConvertedArray
        .FirstName = my2DArray(Counter, 0)
        .LastName = my2DArray(Counter, 1)
      End With
      myArrayList.Add(myConvertedArray)
    Next
    Return myArrayList
  End Function
End Class
 
Public Class myNameClass
  Public Property FirstName As String
  Public Property LastName As String
End Class
Cheers,

Ian
 
No, that function will only work for one custom type. I want one that will work with different type of custom type with different number of properties. I want a function that doesnt know what properties are in the type until it was called. You hard coded the .FirstName and .LastName into it which isnt what i want.
The input of the function needs to be the 2DArray and the customtype it is converting to.. and the output is a 1D array of that customtype.
 
Hi,

Is this example any better? It can pass any custom class type that you have defined to the function and then return an ArrayList of that type with the properties that you have set.

VB.NET:
Public Class Form1
  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim my2DArray(,) As String = {{"Ian", "Ryder"}, {"Bill", "Pearson"}}
    Dim myConvertedArray As New ArrayList
 
    myConvertedArray = ConvertArray(my2DArray, New mySecondNameClass)
    For Each convName As mySecondNameClass In myConvertedArray
      MsgBox(convName.FirstName & " " & convName.LastName)
    Next
  End Sub
 
  Private Function ConvertArray(ByVal my2DArray(,) As String, ByVal myConversionType As Object) As ArrayList
    Dim myArrayList As New ArrayList
    Dim Counter As Integer
 
    'you use the case statement to identify which class type to convert to by using GetType
    'Then you can set different properties as you need to for each defined class type
    'in this case I have just set the same properties for this example but change them as you need
    Select Case myConversionType.GetType
      Case GetType(mySecondNameClass)
        For Counter = 0 To my2DArray.GetUpperBound(0)
          Dim myConvertedArray As New mySecondNameClass
          With myConvertedArray
            .FirstName = my2DArray(Counter, 0)
            .LastName = my2DArray(Counter, 1)
          End With
          myArrayList.Add(myConvertedArray)
        Next
      Case GetType(myThirdNameClass)
        For Counter = 0 To my2DArray.GetUpperBound(0)
          Dim myConvertedArray As New myThirdNameClass
          With myConvertedArray
            .FirstName = my2DArray(Counter, 0)
            .LastName = my2DArray(Counter, 1)
          End With
          myArrayList.Add(myConvertedArray)
        Next
      Case GetType(myNameClass)
        For Counter = 0 To my2DArray.GetUpperBound(0)
          Dim myConvertedArray As New myNameClass
          With myConvertedArray
            .FirstName = my2DArray(Counter, 0)
            .LastName = my2DArray(Counter, 1)
          End With
          myArrayList.Add(myConvertedArray)
        Next
    End Select
    Return myArrayList
  End Function
End Class
 
Public Class myNameClass
  Public Property FirstName As String
  Public Property LastName As String
End Class
 
Public Class mySecondNameClass
  Public Property FirstName As String
  Public Property LastName As String
  Public Property Age As Integer
  Public Property Height As Integer
End Class
 
Public Class myThirdNameClass
  Public Property FirstName As String
  Public Property LastName As String
  Public Property DOB As Date
End Class
Cheers,

Ian
 
And i am using redim preserve is because the amount of data changes. Only the 1st dimension is fix for a particular array. i am redimming the new arrays' 1st dimension which is the 2dArray's 2nd dimension.
But you're using the upper bound of rank 1 of the 2D array as the limit for your For loop and then you're using ReDim Preserve once each the loop. Obviously then the upper bound of rank 1 of the 2D array controls how many elements are in the output array so you could just use that create the output array in the first place and not use ReDim Preserve, This:
VB.NET:
Dim sArray(,) as string 
dim s() as sCustomType
Dim tArray(,) as string 
dim t() as tCustomType
.
.
For i As Integer = 0 To sArray.GetUpperBound(1)
   ReDim Preserve s(i)
   s(i) = New sCustomType
   With s(i)
        .A = sArray(0, i)
        .B = sArray(1, i)
   End With
Next
For i As Integer = 0 To tArray.GetUpperBound(1)
   ReDim Preserve t(i)
   t(i) = New tCustomType
   With t(i)
        .C = tArray(0, i)
        .D = tArray(1, i)
        .E = tArray(2, i)
   End With

Next
should be this:
VB.NET:
Dim sArray(,) as string
Dim tArray(,) as string
.
.
Dim sUpperBound As Integer = sArray.GetUpperBound(1)
Dim tUpperBound As Integer = tArray.GetUpperBound(1)

Dim s(sUpperBound) as sCustomType
Dim t(tUpperBound) as tCustomType

For i As Integer = 0 To sUpperBound
   s(i) = New sCustomType
   With s(i)
        .A = sArray(0, i)
        .B = sArray(1, i)
   End With
Next
For i As Integer = 0 To tUpperBound
   t(i) = New tCustomType
   With t(i)
        .C = tArray(0, i)
        .D = tArray(1, i)
        .E = tArray(2, i)
   End With

Next
I want to create a function that does the conversion from a 2darray of string to an array of a custom type with different number of sub items. so i can just put in a 2darray and its matching custom type, out comes the array in that type.

...

What i was asking is. Can you pass a type to a function. And how to iterate thru each property in a custom type without actually typing the property names.
You might create a generic method or you might just use Reflection, because you'd have to use Reflection to set the properties anyway and you would also have to ensure that the values in the array were either in the same order as the properties appear in the type definition or else in alphabetical order by property name.

Having said all that, I don't think that any of this is necessary. This is presumably related to your earlier question about saving a 2D array in application settings. I suggest that you give both ideas up. Instead, store the data in its own file generated by simply serialising a generic List or array of objects. You can serialise and deserialise a list of any type directly, so all the stuff about 2D arrays and converting goes out the window. 2D arrays have their valid uses but this is not one of them.
 
You mean don't save in my.settings but create a standalone file to save with filestream? Put in my document or something?
 
That's what I meant but it also occurred to me that you could still use My.Settings if you wanted to. Serialisation is done with a Stream as a destination. That is usually a FileStream but you could also MemoryStream. If you were to use binary serialisation then you could serialise to a MemoryStream, get a Byte array from that, convert the array to a base-64 String and then store that in a setting like any other String. To load the data you would simply reverse the steps.
 
Back
Top