List of lists in vb.net - vb.net

I am trying to create lists, that are then inserted into another list.
For some reason the latter list gets overwritten each time I try to add new list item to it.
For the code below, first I want to add items to Temp list and after certain conditions have been met, add the Temp list as an item to the Comp list. After that, the cycle repeats, new and different Temp list should be created and the added to the Comp list as next item. So each item in Comp list should be different.
But in the end I get a Comp list that is filled with Temp lists that are all identical to the last Temp list added.
What am I doing wrong?
Function UniqueValueList2(ByVal InputObject As List(Of Object)) As List(Of List(Of Object))
Dim vc As Integer = InputObject.Count
Dim i As Integer = 1
Dim Temp As New List(Of Object)
Dim Comp As New List(Of List(Of Object))
Dim CurrentObj As String
Dim PrevObj As String
Temp.Add(InputObject(0))
Do While i < vc
CurrentObj = InputObject(i).fieldName
PrevObj = InputObject(i-1).fieldName
If CurrentObj = PrevObj Then
Temp.Add(InputObject(i))
Else
Comp.Add(Temp)
Temp.Clear()
Temp.Add(InputObject(i))
End If
i = i + 1
Loop
Comp.Add(Temp)
UniqueValueList2 = Comp
End Function

Temp is holding the same reference. so making changes on it will change it.And you add and modify the same List
Comp.Add(Temp) 'the same Temp List
Temp.Clear() 'You will clear the same List
Temp.Add(InputObject(i))
So How you should do :
Comp.Add(Temp) 'we add old List
Temp=New List(Of Object) 'Temp now holds reference to new List
Temp.Add(InputObject(i))

This will work:
Comp.Add(Temp.ToList())
Temp.Clear()
Temp.Add(InputObject(i))

Related

how to check that a list contains another list item in VB.Net

I have two lists like this.
Dim List1 As IList(Of String) = New List(Of String)
Dim ListMatch As IList(Of String) = New List(Of String)
I need to figure out if List1 contains all items of ListMatch. How can i do this is VB.Net?
You can use Not SmallCollection.Except(LargeCollection).Any:
Dim containsAll = Not ListMatch.Except(List1).Any()
Documentation of Enumerable.Except:
This method returns those elements in first that do not appear in
second. It does not also return those elements in second that do not
appear in first.
Since Except is a set method, it doesn't take duplicates into account. So if you also want to know if List1 contains the same count of items of ListMatch you could use(less efficient):
Dim list1Lookup = List1.ToLookup(Function(str) str)
Dim listMatchLookup = ListMatch.ToLookup(Function(str) str)
Dim containsSameCount = listMatchLookup.
All(Function(x) list1Lookup(x.Key).Count() = x.Count())

Add Items to datatale per column instead of per row

Half a day of searching made at least my data readable in a datagrid in a wpf app.
My problem is (or what in think is my problem) would be the adding of data in the columns I created.
My source of data is from a dictionary of string, list(of string) with my dictionary key as the header and the List as it's items, also the dictionary and it's content has no fixed length.
And to display my data I used the combination of DataTable and DataGrid
Here's my snippet
Dim files As New Dictionary(Of String, List(Of String))
Dim dt As New DataTable
For Each item As KeyValuePair(Of String, List(Of String)) In files
dt.Columns.Add(item.Key)
For Each file As String In item.Value
Dim dr As DataRow = dt.NewRow
dr(dt.Columns(item.Key).Ordinal) = file
dt.Rows.Add(dr)
Next
Next
DGrid.ItemsSource = dt.AsDataView
It works(somewhat), but as you all have guessed all the succeeding displayed column items after the last one starts where it ended last(looks like a stair).
so the question is do I have to change the way I store my data(dictionary) or I am missing something and this can work as there is a way to add data per column instead of rows?
UPDATE
It's not pretty and I know there is a better solution out there.
What I did first was to just render/instantiate the table and it's content
Dim dt As New DataTable
For Each item As KeyValuePair(Of String, List(Of String)) In files
dt.Columns.Add(item.Key)
For Each file As String In item.Value
Dim dr As DataRow = dt.NewRow
dr(item.Key) = Nothing
dt.Rows.Add(dr)
Next
Next
Then edit it's content:
For Each item As KeyValuePair(Of String, List(Of String)) In files
For file_index As Integer = 0 To item.Value.Count - 1
dt.Rows(file_index)(item.Key) = item.Value(file_index)
Next
Next
This is a bad solution but it works. Is there a better way?
you need to reuse existing rows for this. And add new one only when you have more items then rows.
Dim Files As New Dictionary(Of String, List(Of String))
Dim T As New DataTable, R As DataRow
For Each Pair As KeyValuePair(Of String, List(Of String)) In Files
T.Columns.Add(Pair.Key)
For i As Integer = 0 To Pair.Value.Count - 1
If i < T.Rows.Count Then
R = T.Rows(i)
Else
R = T.NewRow()
T.Rows.Add(R)
End If
R(Pair.Key) = Pair.Value(i)
Next
Next

Search MultiDimensional Array for Starts With

I load a database table into a list of string, and then I want to search the list for any row that starts with a specific set of letters
Ex: Find all rows that start with 'ab'
This is my code:
Dim matchword as string
Dim listOutput As New List(Of String())
For Each row In Table
listOutput.Add({row.Item(0), row.Item(1)})
Next
'Item(0) is a word and Item(1) is a number
How do I search the list to find all the entries (in column 1) that start with matchword
EDIT someone mentioned findAll, how does this work?
See List(Of T).FindAll(Predicate(Of T)).
Dim result As List(Of String()) = listOutput.FindAll(Function(entry As String())
Dim matchword As String = "ab"
Return entry(0).StartsWith(matchword)
End Function)
For Each entry As String() In listOutput
If entry(0).StartsWith(matchword) Then
End If
Next

How to merge two list to have a distinct list without duplicate values in vb.net

I have this problem in vb.net. Lets say I got 2 Lists ListA and ListB both holds objects of same type.
Eg., one of the property of the object is ID. (ID is written in brackets)
ListA ListB
---------------------------
A(3818) A(3818)
B(3819) B(3819)
C(3820) C(3820)
D(3821) D(3821)
E(3823) F(0)
H(3824) G(0)
I(3825)
How do I merge these two Lists to have a new distinct list which holds objects only once whose ID matches and all other objects(whose ID dont match) are simply added to the new list.
Sample output be,
New List
--------
A(3818)
B(3819)
C(3820)
D(3821)
E(3823)
F(0)
G(0)
H(3824)
I(3825)
When I searched I found that AddRange() and Union are some of the methods to do the merge. But i am not able to find if this works for non standard objects(apart from Integer, String)
Use addRange() and then linq with distinct to filter out the duplicates.
Dim b = YourCollection.Distinct().ToList()
Could use a collection bucket
Dim oCol As New Collection
AddTitems(oCol, oListA)
AddTitems(oCol, olistB)
Public Function AddTitems(oSummaryList As Collection, oList As List(Of thing)) As Collection
For Each oThing As thing In oList
If Not oSummaryList.Contains(CStr(oThing.ID)) Then oSummaryList.Add(oList, CStr(oThing.ID))
Next
Return oSummaryList
End Function
Here are a couple simple functions that should do that for you. I'm not sure how efficient they are though. I don't think there is anything built in.
Private Function nameOfFunction(list1 as list(of type), list2 as list(of type)) as list(of type)
Dim result as new list(of type)
for a as integer = 0 to math.max(list1.count, list2.count) - 1 step 1
If a < list1.count AndAlso resultHasID(result, list1(a).ID) = False Then
result.add(list1(a))
end if
If a < list2.count AndAlso resultHasID(result, list2(a).ID) = False Then
result.add(list2(a))
end if
next
End Function
Private Function resultHasID(testList as list(of type), s as string) as boolean
Dim result as Boolean = False
for a as integer = 0 to testlist.count - 1 step 1
if(testlist(a).ID = s) then
result = true
exit for
End if
Next
Return result
End function
For each item as String in ListA
If Not ListB.Contains(item) Then
ListB.Add(item)
End If
Next

vb.net - multi-dimension array list

I've managed to make some single dimension array lists but I can't figure out a multi dimension arraylist.
Here's what I'm trying to do:
I have a database (mdb) with 5 columns that I want each row to be in an array list.
In PHP what I'd typically do is:
$array[$field1] = array($field2,$field3,$field4,$field5);
How I do the same in vb.net so anytime I need to fetch an item for a specific for the row1 I could call it?
For a single dimension I could do the following, but I can't figure out how to add more fields to a single array row:
Dim tmpArrayX As New ArrayList
tmpArrayX.Add(field(0))
tmpArrayX.Add(field(1))
etc...
If you want to use ArrayList, just make it's items contain other ArrayLists.
Or you could use normal arrays as:
Dim multiArray(2, 2) As String
multiArray(0, 0) = "item1InRow1"
multiArray(0, 1) = "item2InRow1"
multiArray(1, 0) = "item1InRow2"
multiArray(1, 1) = "item2InRow2"
Though my personal preference would be to use List as:
Dim multiList As New List(Of List(Of String))
multiList.Add(New List(Of String))
multiList.Add(New List(Of String))
multiList(0).Add("item1InRow1")
multiList(0).Add("item2InRow1")
multiList(1).Add("item1InRow2")
multiList(1).Add("item2InRow2")
Edit: How to find row:
Dim listIWant As List(Of String) = Nothing
For Each l As List(Of String) In multiList
If l.Contains("item1InRow2") Then
listIWant = l
Exit For
End If
Next
' This allows adding rows on the fly....Tested and it works!
Dim multiList As New List(Of List(Of String))
Dim ListRow As Integer = 0
For each record in some_source
dim Country as string = record.country 'from some source
dim Date as Date = record.Date 'from some source
dim Venue as string = record.Venue 'from some source
dim Attendance as string = record.Attendance 'from some source
multiList.Add(New List(Of String))
multiList(ListRow).Add(Country)
multiList(ListRow).Add(Date)
multiList(ListRow).Add(Venue)
multiList(ListRow).Add(Rating)
multiList(ListRow).Add(Attendance)
ListRow = ListRow + 1
next