Error Returning A Dictionary From A Function - vb.net

I have created a function to group data..
Private Function GroupData(ByVal validData As DataSet) As Dictionary(Of [String], List(Of DataRow))()
Dim serviceGroupDataset As DataSet = validData.Clone
Dim grouped As New Dictionary(Of [String], List(Of DataRow))()
Dim groupedRows As List(Of DataRow) = New List(Of DataRow)
For Each r As DataRow In validData.Tables("Detail").[Select]()
Dim key As [String] = r(AuthorizatonConstants.VA_Authorization_ID).ToString().Split("-"c)(0)
If Not grouped.TryGetValue(key, groupedRows) Then
groupedRows = New List(Of DataRow)()
grouped(key) = groupedRows
End If
groupedRows.Add(r)
Next
//COMPILE ERROR
Return grouped
End Function
I am getting a compile error when trying to return the dictionary..
Value of type 'System.Collections.Generic.Dictionary(Of String, System.Collections.Generic.List(Of System.Data.DataRow))' cannot be converted to '1-dimensional array of System.Collections.Generic.Dictionary(Of String, System.Collections.Generic.List(Of System.Data.DataRow))'.
How can I return the grouped dictionary from the function?

Your method signature is returning a Dictionary-array(because of the following ()), i assume you want to return a single dictionary.
You can use this Linq-To-DataTable approach which is more comprehensible:
Private Function GroupData(ByVal validData As DataSet) As Dictionary(Of String, List(Of DataRow))
Dim groups = From row In validData.Tables("Detail")
Let id = row.Field(Of String)(AuthorizatonConstants.VA_Authorization_ID).Split("-"c)(0)
Group row By id Into RowGroup = Group
Dim grouped As Dictionary(Of String, List(Of DataRow)) = groups.
ToDictionary(Function(grp) grp.id, Function(grp) grp.RowGroup.ToList())
Return grouped
End Function

Related

from list to string with formatting

i have a function getSelectedNumbers that take as input 3 list of number. after a manipulation i need to obtain a string in the format
"[1_3,10,20,30,500],[1_1,2],[]"
if the list is empty i need to have in the string the "[]" char
i wrote the below function but i need to manage the empty case.
Based on comment of Anu6is :
i was able to rewrite my code as below
'''vb
Public Function getSelectedNumbers() As String
Dim selectedNumbers1 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel1.Find(".//div[#class='selected']")
Dim selectedNumbers2 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel2.Find(".//div[#class='selected']")
Dim selectedNumbers3 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel3.Find(".//div[#class='selected']")
Dim list1 As New List(Of String)
Dim list2 As New List(Of String)
Dim list3 As New List(Of String)
For i As Integer = 0 To selectedNumbers1.Count -1
list1.Add(selectedNumbers1(i).GetAttributeValue("innerText").ToString)
Next i
For i As Integer = 0 To selectedNumbers2.Count -1
list2.Add(selectedNumbers2(i).GetAttributeValue("innerText").ToString)
Next i
For i As Integer = 0 To selectedNumbers3.Count -1
list3.Add(selectedNumbers3(i).GetAttributeValue("innerText").ToString)
Next i
'Create List of List
Dim selectedNumbersList As New List(Of List(Of String)) From {list1, list2, list3}
Dim builder As New StringBuilder 'Used to build the output
'Convert all the list in the correct string format using the join
For Each listX As List(Of String) In selectedNumbersList
builder.Append("[1_").Append(String.Join(",", listX)).Append("],") 'String.Join() give you a comma delmited string
Next
'Remove the last, and the [1_] that are not needed
Dim strSelectedNunmber As String = builder.ToString().TrimEnd(","c)
strSelectedNunmber = strSelectedNunmber.ToString().Replace("[1_]","[]")
Return str
End Function
'''
now my question is there is a better way to generate the list1 list2 list3 ?
This is assuming that Element is simply an Integer
Public Function getSelectedNumbers() As String
Dim selectedNumbers1 As New List(Of Integer) From {20, 30, 500, 10, 3} 'Unordered list
Dim selectedNumbers2 As New List(Of Integer) From {1, 2, 500} 'Ordered list
Dim selectedNumbers3 As New List(Of Integer) 'empty list
Dim selectedNumbersList As New List(Of List(Of Integer)) From {selectedNumbers1, selectedNumbers2, selectedNumbers3}
Dim builder As New StringBuilder 'Used to build the output
For Each list In selectedNumbersList
list.Sort() 'Sort your list
builder.Append("[").Append(String.Join(",", list)).Append("],") 'String.Join() give you a comma delmited string
Next
Return builder.ToString.TrimEnd(","c) 'Remove the final comma (,) and return the formatted string
End Function
[3,10,20,30,500],[1,2,500],[]
Does this work for you?
Dim selectedNumbers1 As New List(Of Integer) From {20, 30, 500, 10, 3}
Dim selectedNumbers2 As New List(Of Integer) From {1, 2, 500}
Dim selectedNumbers3 As New List(Of Integer)
'either make 3 loops or 1, but you have to make a list of lists first
Dim selectedNumbersList As New List(Of List(Of Integer)) From {selectedNumbers1, selectedNumbers2, selectedNumbers3}
For Each listX In selectedNumbersList
listX.Sort()
Dim ReturnString As String = "["
If listX.Count > 0 Then
For Each itemvalue In listX
ReturnString &= itemvalue & ","
Next
ReturnString = ReturnString.Remove(ReturnString.Length - 1)
End If
ReturnString &= "]"
Debug.Print(ReturnString)
Next
'[3,10,20,30,500]
'[1,2,500]
'[]

Join multiple List(Of String) in VB.NET

I need to join these three List(Of String):
Dim lst1 As New List(Of String) From {"man1"}
Dim lst2 As New List(Of String) From {"/1child", "/2child"}
Dim lst3 As New List(Of String) From {"/1age", "/2age"}
To get output like this List(Of String):
man1/1child/1age
man1/1child/2age
man1/2child/1age
man1/2child/2age
What is most effictive way? LINQ way? Thanks!
Both of these variants works:
Dim result = lst1.SelectMany(Function(m) lst2.SelectMany( _
Function(c) lst3.[Select](Function(a) m + c + a))).ToList
Dim result2 = lst1.SelectMany(Function(l) lst2.SelectMany( _
Function(ls) lst3.Select(Function(lst) String.Format("{0}{1}{2}", l, ls, lst))))

How would I write this VB.Net loop functionally?

I have a VB.Net function that translates a NameValueColletion to an IDictionary. How would I write this functionally (with Select, etc. instead of a loop)?
<Extension()>
Public Function ToDictionary(ByVal source As NameValueCollection)
As IDictionary(Of String, String)
Dim ret = New Dictionary(Of String, String)
Dim keys = source.Keys
For Each key In keys
Dim sKey = TryCast(key, String)
Dim sVal = TryCast(source(key), String)
If sKey Is Nothing OrElse sVal Is Nothing Then Continue For
ret(sKey) = sVal
Next
Return ret
End Function
Return source.Cast(Of String)().
ToDictionary(Function(key) key, Function(key) source(key))

How to add List as value in Hashtable

In vb.net If I have HashTable,key is integer and the value is a list of integers, how to append integers to the value of a given key,
I have tried it but each time I found the integer last added only, (the list only has the last item added).
Here is my code , where dt is DataTable object
Dim dt = report.getEvaluationReportByObjectiveGroupId(29)
Dim data As New Hashtable()
Dim dataEntry As DictionaryEntry
Dim res As String
For Each row As DataRow In dt.Rows
Dim strYear = row.Item("Year")
Dim strData = row.Item("EmpCount")
If data.ContainsKey(strYear) Then
Dim newCountArr As List(Of Int32) = DirectCast(data(strYear), List(Of Int32))
' newCountArr.AddRange(data(strYear))
newCountArr.Add(strData)
' data.Remove(strYear)
' data.Add(strYear, newCountArr)
Else
Dim countArr As New List(Of Integer)
countArr.Add(strData)
data.Add(strYear, countArr)
End If
' data.Add(strYear, strData)
Next row
I would suggest to use the strongly typed Dictionary(Of Int32, List(Of Int32)) instead, it works similar. But anyway, here's the HashTable approach:
Dim table = New Hashtable
Dim list = New List(Of Int32)
For i = 1 To 999
list.Add(i)
Next
table.Add(1, list)
' somewhere else you want to read the list for a given key (here 1) '
Dim list1 As List(Of Int32) = DirectCast(table(1), List(Of Int32))
list.Add(1000) ' add another integer to the end of the list '
' note: you don't need to add the list to the HashTable again '
Edit: Since you've posted your code, here's the corrected:
For Each row As DataRow In dt.Rows
Dim strYear = row.Field(Of Int32)("Year")
Dim strData = row.Field(Of Int32)("EmpCount")
Dim list As List(Of Int32)
If data.ContainsKey(strYear) Then
list = DirectCast(data(strYear), List(Of Int32))
Else
list = New List(Of Int32)
data.Add(strYear, list)
End If
list.Add(strData)
Next row

Building a multidimensional array in vb.net

I'm trying to build up a multidimensional array which will hold two bits of info for each record in a database e.g. id, description.
This is what I am currently doing.
Dim mArray(,) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
The problem I have here is that it doesn't like the i in mArray(i,0). Anyone have any ideas about this? This is the error that is given Object reference not set to an instance of an object.
Thanks for any and all help.
Nalum
Why not rather make use of List Class and Dictionary Class
You can rather then create a List of Dictionaries, with the key and value both strings. The key can then represent your key (id and description in your example, and the value can be what ever was stored).
Something like
Dim values As New List(Of Dictionary(Of String, String))()
and then in the while loop something like
values.Add(New Dictionary(Of String, String)() From { _
{"id", cmdReader.Item("id")} _
})
values.Add(New Dictionary(Of String, String)() From { _
{"description", cmdReader.Item("description")} _
})
You could then use foreach
For Each value As Dictionary(Of String, String) In values
Dim id As String = value("id")
Dim description As String = value("description")
Next
Or a for
For i As Integer = 0 To values.Count - 1
Dim value As Dictionary(Of String, String) = values(i)
Dim id As String = value("id")
Dim description As String = value("description")
Next
Try this
Dim mArray(1,1) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
ReDim Preserve mArray(i,1)
End While
The problem is that you are not initializing the array.
This should work, until i will not reach the limits set in the initialization.
Dim mArray(100,100) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
But if the array limits are not known I suggest to follow astander's suggestion.
This works for me:
Dim values As New List(Of Dictionary(Of String, String))()
values.Add(New Dictionary(Of String, String)() From {{"quarter", q1.ToString}, {"year", y1.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q2.ToString}, {"year", y2.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q3.ToString}, {"year", y3.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q4.ToString}, {"year", y4.ToString}})
For Each value As Dictionary(Of String, String) In values
Dim quarter As String = value("quarter")
Dim year As String = value("year")
Debug.Print(quarter & "/" & year)
Next
Correct it by
Dim mArray(,) As String = ""