In some languages there are short-cuts when adding items into collections.
I have the following:
Sub Main()
Dim letters As List(Of String)
letters = New List(Of String)
letters.Add("a")
letters.Add("1")
letters.Add("2")
letters.Add("3")
letters.Add("x")
letters.Add("d")
End Sub
Is there a short hand way of executing this. The following does not work but maybe there's some similar syntax in VB.NET:
Sub Main()
Dim letters As List(Of String)
letters = New List(Of String){"a","1","2","3","x","d"}
End Sub
Since VS2010 you should be able to do this in VB.NET:
Dim letters As List(Of String)
letters = New List(Of String) From {"a","1","2","3","x","d"}
The From can be swapped for brackets:
letters = New List(Of String) ({"a","1","2","3","x","d"})
Nice related article: MSDN HERE
You could use a string array (input() in my example). Another option is pass the list of strings to the constructor or use List.AddRange.
Dim input() As String = { "A", _
"B", _
"C" }
Dim listA As New List(Of String)(input)
dim listB as New List(Of String)
listB.AddRange(input)
HTH Wade
Related
I noticed something while using a list of lists. It seems that if I have a List(Of String) and a List(Of List(Of String)) that when I add the List(Of String) to the List(Of List(Of String)) that the list of strings gets passed by reference.
For example in the following code:
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim listRow As New List(Of String)
Dim listTable As New List(Of List(Of String))
listRow.Add("Apple")
listRow.Add("Red")
listTable.Add(listRow)
MsgBox(listTable(0)(0))
MsgBox(listTable(0)(1))
listRow(0) = "Banana"
listRow(1) = "Yellow"
MsgBox(listTable(0)(0))
MsgBox(listTable(0)(1))
End Sub
The first pair of messages will display "Apple" and "Red". Then, after updating listRow, it will display "Banana" and "Yellow". To me this means that the list was added by reference and not by value. I'm looking for confirmation on this, and perhaps a better explanation if there is one?
This is how I've been handling it:
Sub AddListItemToMainList(myListRow As List(Of String), myListTable As List(Of List(Of String)))
Dim newList As New List(Of String)
newList.Add(myListRow(0))
newList.Add(myListRow(1))
myListTable.Add(newList)
End Sub
Then just replace listTable.Add(listRow) with AddListItemToMainList(listRow, listTable). Obviously my code isn't very dynamic, I'm hardcoding the first and second element, but I'm just testing right now getting the logic and whatnot correct.
If there is a more elegant solution I'm always open to advice.
Similar question here, but no answer : vb.net dictionary of string,dictionary...after filling readout always empty
I fill as List(Of String) with rows of text from a file and then add it to a Dictionary. The method I use to fill this Dictionary works as it should. I create:
Private dictDictionary As Dictionary(Of String, List(Of String))
loop through the text file and adding each row to a list then add that list to the dictionary with the file name as key like so:
dictDictionary.Add(sFileName, sFileRows)
sFileRows is a List(Of String) containing a MAX of 1056 elements that I need to move around based on specific options. The problem I'm having is accessing this List(Of Strings) by the Key.
I've tried:
For Each kvp As KeyValuePair(Of String, List(Of String)) In dictDictionary
Dim sKey As String = kvp.Key
Dim tempRows As List(Of String) = New List(Of String)
tempRows = dictDictionary.item(sKey)
Next
No matter what I try when I assign the List(Of String) in the Dictionary to a new List it is always empty. But the original dictionary has the rows in the List(Of String) that I read from the text file.
First Method that fills the dictionary:
Private Sub GetInfo()
Try
Dim sFileName As String = String.Empty
Dim sFileRows As List(Of String) = New List(Of String)
If IO.Directory.Exists("some directory")Then
Dim Files() As String = IO.Directory.GetFiles("directory and file type")
For Each File As String In Files
sFileName = Path.GetFileName(File)
Dim rdrRows As StreamReader = New StreamReader(File)
Dim sString As String
While rdrRows.Peek() >= 0
sString = rdrRows.ReadLine()
sFileRows.Add(sString)
End While
'Actually adding the info to the dictionary
dictDictionary.Add(sFileName, sFileRows)
rdrRows.Dispose()
sFileRows.Clear()
Next
End If
Catch ex As Exception
End Try
End Sub
Second Method to manipulate the order of elements in the List(Of String)
Private Sub ChangeStructure()
For Each kvp As KeyValuePair(Of String, List(Of String)) In dictDictionary
Dim rows As List(Of String) = kvp.Value
For Each item As String In rows
MessageBox.Show(item.ToString)
Next
Next
End Sub
There is nothing in the List(Of String) now but there was when it was filled in GetInfo()
Should be as easy as
Dim data = New Dictionary(Of String, List(Of String)) From _
{
{"Foo", New List(Of String) From {"1", "2", "3"}},
{"Bar", New List(Of String) From {"4", "5", "6"}}
}
For Each kvp in data
Console.WriteLine(kvp.Key & " says:")
For Each str in kvp.Value
Console.WriteLine(str)
Next
Next
For Each kvp As KeyValuePair(Of String, List(Of String)) In dictDictionary
Dim rows As List(Of String) = kvp.Value
If rows Is Nothing Then Continue
For Each item As String in rows
'...
Next item
Next kvp
You're are using kvp.Key, why are you not using kvp.Value?
For Each kvp As KeyValuePair(Of String, List(Of String)) In dictDictionary
Dim sKey As String = kvp.Key
Debug.Print("Filename: " & sKey)
Dim tempRows As List(Of String) = kvp.Value
Debug.Print("# of Lines: " & tempRows.Count)
Debug.Print("------------------------------")
For Each line As String In tempRows
Debug.Print(line)
Next
Debug.Print("------------------------------")
Debug.Print("")
Next
The problem is this line:
sFileRows.Clear()
List(Of String) is a reference type. After you fill the list and add it to the dictionary, you clear it, so it is empty when you try to access it later.
The solution is to create a new list each time in the loop. In other words, move this line:
Dim sFileRows As List(Of String) = New List(Of String)
inside the For loop and get rid of the call to .Clear()
Using VB.net
I have two List(Of String)
Here's how Im finding the common items between the two lists:
Sub Main()
Dim lstOne As New List(Of String)() _
From {"Jim", "Jack", "Kate", "Nope"}
Dim lstTwo As New List(Of String)() _
From {"Jack", "Nope", "Jim"}
Dim lstNew As IEnumerable(Of String) = Nothing
lstNew = lstOne.Intersect(lstTwo, StringComparer.OrdinalIgnoreCase)
End Sub
I want to use Linq to find the uncommon items in these two lists.
How can I do that?
Like this:
Sub Main()
Dim lstOne As New List(Of String)() _
From {"Jim", "Jack", "Kate", "Nope"}
Dim lstTwo As New List(Of String)() _
From {"Jack", "Nope", "Jim"}
Dim lstNew As IEnumerable(Of String) = Nothing
lstNew = lstOne.Intersect(lstTwo, StringComparer.OrdinalIgnoreCase)
Dim uncommon As IEnumerable(Of String) = lstOne.Union(lstTwo).Except(lstNew, StringComparer.OrdinalIgnoreCase)
For Each element As String In uncommon
Console.WriteLine(element)
Next
End Sub
Output:
Kate
To stick within pure LINQ, you can use Except:
Dim inOneNotTwo As IEnumerable(Of String) = lstOne.Except(lstNew)
Dim inTwoNotOne As IEnumerable(Of String) = lstTwo.Except(lstNew)
Alternatively, you could use HashSet(Of T) and SymmetricExceptWith:
Dim strings As HashSet(Of String) = new HashSet(Of String)(lstOne)
strings.SymmetricExceptWith(lstTwo)
In the following example, does it matter if i pass the List(T) object in both functions ByRef or ByVal?
Is this right that as List is a reference type so value will always be changes even if i pass the object ByVal.
Would it be better if i pass the object byRef in function "ListChanged" as list is being updated.
Public Class MyClass_
Public Sub TestMethod()
Dim List_1 As New List(Of Integer)()
Dim List_2 As New List(Of Integer)()
List_1.Add(100)
List_2.Add(50)
List_1 = ActualListNotChanged(List_1) '---101
List_2 = ListChanged(List_2) '---50,51
End Sub
Private Function ActualListNotChanged(ByVal lst As List(Of Integer)) As List(Of Integer)
Dim nList As New List(Of Integer)()
For Each item As Integer In lst
If item <> 50 Then
nList.Add(101)
End If
Next item
Return nList
End Function
Private Function ListChanged(ByVal lst As List(Of Integer)) As List(Of Integer)
lst.Add(51)
Return lst
End Function
End Class
In your example, ByVal (the default) is the most appropriate.
Both ByVal and ByRef allow you to modify the list (e.g. add/remove items).
ByRef also allows you to replace the list with a different list, e.g.
Dim List1 As New List(Of Int)
List1.Add(1)
ListReplacedByVal(List1)
' List was not replaced. So the list still contains one item
Debug.Assert(List1.Count = 1) ' Assertion will succeed
ListReplacedByRef(List1)
' List was replaced by an empty list.
Debug.Assert(List1.Count = 0) ' Assertion will succeed
Private Sub ListReplacedByVal(ByVal lst As List(Of Integer))
lst = New List(Of Int)
End Sub
Private Sub ListReplacedByRef(ByRef lst As List(Of Integer))
lst = New List(Of Int)
End Sub
In general you should use ByVal. The object you pass can be modified (in the sense that you can call its methods and property setters to change its state). But it can't be replaced by a different object.
I'd say best practise would be to pass using ByRef if (and only if) you are changing the list. Not a long answer, but it's short and sweet!
How would I make use of a List(of String) in a structure in vb.net. for example
Structure examplestrut
Public exampleslist As List(Of String)
End Structure
How would I call exampleslist.add("example 1")?
Like this:
Dim myStruct as ExampleStruct
myStruct.exampleList = new List(Of String)()
myStruct.exampleList.Add("Hi there!")
Its also worth mentioning that if you already have a 'myStruct' declared earlier in the program and you need to empty it, you use
myStruct.exampleList = new List(Of String)()
rather than
myStruct.exampleList.Clear()