Short way to create arrays? - vb.net

In VB.NET, I create my arrays like
Dim myArray = New ArrayList
But isn't there a way to create an array with elements without having to make a variable?
In Ruby, the long way was
array = Array.new
And the simple, non-variable way was just
[element,element,...]

Well, things you can do with primitive (and String) arrays:
Dim array As New String()
Dim array As New String() { "one", "two", "three" }
If (New String() { "one", "two", "three" }).Contains("one") Then
' Do something for "one"
End If
If you move to VB.NET 2010 you will get some extra array initialization features, but if you're using 2008 or below the shortest you can get your lists created might be something like this:
Dim list As New List(Of String)
list.AddRange(New String() { "one", "two", "three" })
And to touch on the point of declaring things without assigning them to a variable: .NET is strongly typed, so while you don't always have to declare a variable, your objects will always need to be of a single type (and one you need to specify through a New).

I'm not sure just how useful such a beast is since, without a name, you can't easily access the elements of it.
I know C has a feature that allows this with "one-shot" accesses like:
char hexchar = "0123456789abcdef"[nybble];
but, after that statement's finished the char array making up that string is no longer accessible.
If you want an array you can access continuously, I suspect it will need an identifying name. I might be wrong, I haven't used VB since VB6 but even if it's possible, it's a dubious language feature (IMO).

You can do a few things.
Public Sub Main()
Dim xs = New Integer() {1, 2, 3}
CType({1, 2, 3}, Integer()).CopyTo(...)
Dim s2 = Sum({1, 2, 3})
End Sub
Public Function Sum(ByVal array As Integer()) As Integer
Return array.Sum()
End Function
Is this the kind of thing you're after?

For Each foo As String In New String() {"one", "two", "three"} 'an array with no name - "On the first part of the journey..."
Debug.WriteLine(foo)
Next

Related

VB.Net equivalent of Javascript's .Map function

Given an array of strings, say: Dim array1 As String() = {"1", "2", "3"} what is the best way to copy that array and perform an action on each element?
In other words, what is the best way to copy that array to come up with: array2 as integer() = {1, 2, 3}
For example, something similar to JavaScript's .Map function:
var numbers = [4, 9, 16, 25];
function myFunction() {
x = document.getElementById("demo")
x.innerHTML = numbers.map(Math.sqrt);
}
// Result: 2, 3, 4, 5
If it isn't possible in one line - as I suspect it isn't - what is your quickest alternative? Thanks!
If you don't want to use any LINQ extension methods, but you are okay with using lambda expressions, you can still do it in one line using Array.ConvertAll:
Dim input() As String = {"1", "2", "3"}
Dim output() As Integer = Array.ConvertAll(input, Function(x) Integer.Parse(x))
However, it does beg the question: why not just use LINQ, at that point, since it's effectively the same thing:
Dim input() As String = {"1", "2", "3"}
Dim output() As Integer = input.Select(Function(x) Integer.Parse(x)).ToArray()
The classic imperative way to do this in VB, without using LINQ or lambdas, would be a for-loop:
Dim input() As String = {"1", "2", "3"}
Dim output(LBound(input) To UBound(input)) As Integer
For i As Integer = LBound(input) To UBound(input)
output(i) = Integer.Parse(input(i))
Next
I would like to add that, similar to JavaScript, .NET's map equivalent Select also supports method groups as well as lambdas.
Here's an example using a lambda:
Dim output = input.Select(Function(x) SomeMethod(x)).ToArray()
Here's an example using a method group. Since parenthesis on method invocations are optional in VB.NET, the additional AddressOf keyword is required:
Dim output = input.Select(AddressOf SomeMethod).ToArray()
For completeness, here's an example using the LINQ query syntax, which is just syntactic sugar for the first example:
Dim output = (From x In input Select SomeMethod(x)).ToArray()
If you don't want to use LINQ here is the classic way, a loop:
Dim numbers = {4, 9, 16, 25}
For i As Int32 = 0 To numbers.Length - 1
numbers(i) = CInt(Math.Sqrt(numbers(i)))
Next

Variables refer to the same instance

Within my learning curve I play around with converting List and IEnumerable between each other.
What I am surprised with is that after executing EditMyList procedure MyIEnumerable contains the same data for each DBTable object as MyList. However I have modified MyList only, without assigning it to MyIEnumerable once List has been modified.
Can you explain what happened here and why MyList and MyEInumerable refer to the same instance?
Public Class DBTable
Public Property TableName As String
Public Property NumberOfRows As Integer
End Class
Public Sub EditMyList
Dim MyList As New List(Of DBTable)
MyList.Add(New DBTable With {.TableName = "A", .NumberOfRows = 1})
MyList.Add(New DBTable With {.TableName = "B", .NumberOfRows = 2})
MyList.Add(New DBTable With {.TableName = "C", .NumberOfRows = 3})
Dim MyIEnumerable As IEnumerable(Of DBTable) = MyList
For Each item In MyList
item.NumberOfRows += 10
Next
End Sub
UPDATE: string case where at the end b is not equal to a. String is also reference type, so assigning one variable to other one we shall copy just reference. However at the end there is different result than in the first example (explained by #Sefe)
Dim a As String
Dim b As String
a = "aaa"
b = "bbb"
a = b
' At this point a and b have the same value of "bbb"
a = "xxx"
' At this point I would expect a and b equal to "xxx", however a="xxx" but b="bbb"
A List is a reference type. That means it is created on the heap and your MyList variable contains just a reference (sometimes incorrectly called "pointer") to the list. When you assign MyList to MyEnumerable you don't copy the whole list, you just copy the reference. That means all changes you make to the (the one) list, is reflected by all the references.
If you want a new list you need to create it. You can use the list constructor:
Dim MyIEnumerable As IEnumerable(Of DBTable) = New List(Of DBTable)(MyList)
Since you don't need a list, but an IEnumerable you can also call the list's ToArray method:
Dim MyIEnumerable As IEnumerable(Of DBTable) = MyList.ToArray
You can also use LINQ:
Dim MyIEnumerable As IEnumerable(Of DBTable) = MyList.ToList
As far as the behavior of String is concerned, strings in .net are immutable. That means once created, they can not be changed. String operations (for example concatinations) will always create new strings. In other words: the copy operation you have to do manually for your lists is done automatically for strings. That's why you see similar behavior for strings as for value types.
Also, the assignment operation in your question would also still behave the same if strings were mutable. When you assign a = "xxx", you update the reference of afrom "bbb" to "xxx". That however does not affect b, which still keeps its old reference.
Use ToList() extension method for creating another List
Dim newCollection = MyList.ToList()
But notice that instances of DBTable still will reference to the same items
For creating "full" copy you need create new instances of DBTable for every item in the collection
Dim newCollection = MyList.Select(Function(item)
return new DBTable
{
.TableName = item.TableName,
.NumberOfRows = item.NumberOfRows
}
End Function).ToList()
For Each item in MyList
item.NumberOfrows += 10 ' will not affect on the newCollection items
Next

Convert integer array to string array

whats the easiest way to convert an array of integers into string form? I'm trying to copy the whole array of integers into strings.
{1, 2, 3}
to
{"1", "2", "3"}
The easiest method would be to use the Select extension method which is provided by LINQ:
Dim intArray() As Integer = {1, 2, 3}
Dim strArray() As String = intArray.Select(Function(x) x.ToString()).ToArray()
If you don't want to, or cannot use LINQ, you can use the Array.ConvertAll method, which is almost as easy:
Dim strArray() As String = Array.ConvertAll(Of Integer, String)(intArray, Function(x) x.ToString())
EDIT
Based on your comments, below, it looks like you need to convert from an ArrayList of integers to an ArrayList of strings. In that case, you could do it like this:
Dim intArray As New ArrayList({1, 2, 3})
Dim strArray As New ArrayList(intArray.ToArray().Select(Function(x) x.ToString()).ToArray())
Although, at that point, it's starting to get a bit messier. It's probably easier to just do a standard loop, like this:
Dim myArray As New ArrayList({1, 2, 3})
For i As Integer = myArray.Count - 1 To 0 Step -1
myArray(i) = myArray(i).ToString()
Next
For what it's worth, though, unless you are still on a really old version of the .NET Framework, you really ought to be using the List(Of T) class rather than the ArrayList class, in most cases.

How to assign a value to an array from a combobox

The code I have is:
Dim Dbase() As String = Nothing
Dbase(0) = Db_ComboBox.Text
I have declared Dbase as array and assigned Nothing, Db_ComboBox is a combobox.
For that assignment statement, I'm getting the following error: "Reference 'Dbase' has a value of 'Nothing'"
What is the reason for this error, and how can I take the value from the combobox and save it in the array?
You need to change this:
Dim Dbase() As String = Nothing
to this (declare an array of 1 element):
Dim Dbase(0) As String
And then this line will work:
Dbase(0) = Db_ComboBox.Text
If you need to change your array size you can use Redim or Redim preserve, as required.
If you anticipate contents of Dbase to change often, I am all with #Joel's suggestion about switching to List(Of String) instead of handling array sizes manually.
Let's look at your code:
Dim Dbase() As String = Nothing
Dbase(0) = Db_ComboBox.Text
Especially the first line. That first line creates a variable that can refer to an array, but the = Nothing portion explicitly tells it, "Do not create a real array here yet". You have, effectively, a pointer that doesn't point to anything.
I get here that what you really need is a List collection that you can append to over time:
Dim Dbase As New List(Of String)()
Dbase.Add(Db_ComboBox.Text)
Dbase() IS NOTHING. Look at this example:
cargoWeights = New Double(10) {}
atmospherePressures = New Short(2, 2, 4, 10) {}
inquiriesByYearMonthDay = New Byte(20)()() {}
That's how you declare arrays.
More examples: http://msdn.microsoft.com/en-us/library/vstudio/wak0wfyt.aspx

VB.Net Initialising an array on the fly

I wrote this - very simple - function, and then wondered does VB have some pre-built functionality to do this, but couldn't find anything specific.
Private Shared Function MakeArray(Of T)(ByVal ParamArray args() As T) As T()
Return args
End Function
Not so much to be used like
Dim someNames() as string = MakeArray("Hans", "Luke", "Lia")
Because this can be done with
Dim someNames() as string = {"Hans", "Luke", "Lia"}
But more like
public sub PrintNames(names() as string)
// print each name
End Sub
PrintNames(MakeArray("Hans", "Luke", "Lia"))
Any ideas?
Any reason not to do:
Dim someNames() as string = New String(){"Han", "Luke", "Leia"}
The only difference is type inference, as far as I can tell.
I've just checked, and VB 9 has implicitly typed arrays too:
Dim someNames() as string = { "Han", "Luke", "Leia" }
(This wouldn't work in VB 8 as far as I know, but the explicit version would. The implicit version is necessary for anonymous types, which are also new to VB 9.)
Dim somenames() As String = {"hello", "world"}
The following codes will work in VB 10:
Dim someNames = {"Hans", "Luke", "Lia"}
http://msdn.microsoft.com/en-us/library/ee336123.aspx
PrintNames(New String(){"Hans", "Luke", "Lia"})
Microsoft recommends the following format
Dim mixedTypes As Object() = New Object() {item1, item2, itemn}
per http://msdn.microsoft.com/en-US/library/8k8021te(v=VS.80).aspx
Note, you don't have to specify the size of new Array, as that is inferred from the initialized count of args. If you do want to specify the length, you specify not the "length" but index number of last space in array. ie. New Object(2) {0, 1, 2} ' note 3 args.