Group Dictionary values of a particular key - vb.net

I have a Dictionary of String and a list of type variable. i.e.
Dim search As Dictionary(Of String, List(Of TypeResult))
My query is if I get 3 key-value pairs inside the dictionary and I want to groupby the values of only a particular key (say key no. 3), then how to do the same.
By groupby I want to eliminate any duplicate values coming in the List of a particular key.
Any code snippets or suggestions would be great.
Thanks In Advance.

I want to eliminate any duplicate values coming in the List of a particular key
There are a few ways to do this, depending on how and when you add items to the list for a particular key and at what time you need them to be without duplicates.
You could do it like this, to ensure that there are never any duplicate values in the list.
Sub AddItem(ByVal key As String, ByVal val as TypeResult)
Dim values As List(Of TypeResult)
If (search.TryGetValue(key, values)) Then
If (Not values.Contains(val)) Then
values.Add(val)
End If
Else
values = new List(Of TypeResult)()
values.Add(val)
search.Add(key, values)
End If
End Sub
Note that TypeResult must provide an Equals and GetHashCode implementation, otherwise the call to Contains may not provide you with the desired behavior.
Another option is to filter out duplicate values when they are being returned to someone asking for the values of a specific key.
Function DistinctValuesFor(ByVal key As String) As IEnumerable(Of TypeResult)
Dim values As List(Of TypeResult)
If (search.TryGetValue(key, values)) Then
DistinctValuesFor = values.Distinct()
Else
DistinctValuesFor = Enumerable.Empty(Of TypeResult)()
End If
End Function

Related

Dataset with Datatable

I am trying to check if my dictionary contains values in my dataset.datatable and if its quantities in the second column of the dataset are less than or greater than the quantities in my datatable. I tried using the SELECT method but it doesn’t seem to work, I get the error BC30469 reference to non-shared member requires object reference?
I was just trying to do a simple search in the table first to see if I can even do that..... apparently not. Thanks for the help!
Dim row As DataRow = DataSet.DataTable.Select("ColumnName1 = 'value3'")
If Not row Is Nothing Then
searchedValue = row.Item("ColumnName2")
End If
You could get a dictionary to compare with the one you already have like this (assuming your key is a string and the amount an Int32 and that your dataset contains only one table):
Dim myDBDict As Dictionary(Of String, Int32) =
From e In myDataSet.Tables(0).Rows.Cast(Of DataRow).ToDictionary(Of String, Int32)(
Function(e) e.Field(Of String)("MyIDColumn"),
Function(e) e.Field(Of Int32)("myAmountColumn"))

Can I use a method that returns a list of strings in SSRS report code as the headers in a tablix?

I have table that needs to contain 50 columns for each half hour in the day (+2 for daylight savings). So each column will be HH1, HH2, HH3... HH50.
I have written this piece of code in the report properties code section.
Function GetHH() As List(Of String)
Dim headers As List(Of String) = new List(Of String)
For index As Integer = 1 to 50
headers.Add("HH" & index)
Next
return headers
End Function
Is there a way to use the output of this function as the headers of my tablix? Or will I need to add the headers to some sort of dataset in the database and add it from there?
The column group functionality would be well suited for this. As you mentioned, you would need to write a SQL statement to return these values in a dataset. Then you can set your column group to group on these values. This way your table always gets the right number of columns and you don't have to add them manually.

Store a two value combination

I want to store a two value combination but cannot find the right class. I know I could do it with a two dimentional array but is there another way since I always have to do the redimentionalisation. I know about the dictionary but there is the first value always the key.
Example:
I have a dgv and want to collect the rownumbers with duplicates. I iterate throu the dgv and collect 1 and 4, 20 and 33 and so on and store this combinations to use them somewhere else.
You can use collection of Tuple. For example :
Dim tuples As New List(Of Tuple(Of Integer, Integer))
tuples.Add(Tuple.Create(1, 4))
tuples.Add(Tuple.Create(20, 33))
One way would be with a Dictionary(Of DataGridViewRow, List(Of Integer)). The list would contain the rows holding the values in the key. This will work if you get more than 2 rows trhat are duplicates.

Simplest/fastest way to check if value exists in DataTable in VB.net?

I have a DataTable (currently with multiple columns but I could just grab one column if it makes it easier). I want to check if a String value exists in a column of the DataTable. (I'm doing it many times so I want it to be reasonably fast.)
What is a good way to do this? Iterating through the DataTable rows each time seems like a bad way. Can I convert the column to a flat List/Array format, and use a built in function? Something like myStrList.Contains("value")?
You can use select to find whether that value exist or not. If so, it returns rows or it will not. Here is some sample code to help you.
Dim foundRow() As DataRow
foundRow = dt.Select("SalesCategory='HP'")
If the data in your DataTable doesn't change very often, and you search the DataTable multiple times, and your DataTable contains many rows, then it's likely going to be a lot faster to build your own index for the data.
The simplest way to do this is to sort the data by the key column so that you can then do a binary search on the sorted list. For instance, you can build an index like this:
Private Function BuildIndex(table As DataTable, keyColumnIndex As Integer) As List(Of String)
Dim index As New List(Of String)(table.Rows.Count)
For Each row As DataRow in table.Rows
index.Add(row(keyColumnIndex))
Next
index.Sort()
Return index
End Function
Then, you can check if a value exists in the index quickly with a binary search, like this:
Private Function ItemExists(index As List(Of String), key As String) As Boolean
Dim index As Integer = index.BinarySearch(key)
If index >= 0 Then
Return True
Else
Return False
End If
End Function
You could also do the same thing with a simple string array. Or, you could use a Dictionary object (which is an implementation of a hash table) to build a hash index of your DataTable, for instance:
Private Function BuildIndex(table As DataTable, keyColumnIndex As Integer) As Dictionary(Of String, DataRow)
Dim index As New Dictionary(Of String, DataRow)(table.Rows.Count)
For Each row As DataRow in table.Rows
index(row(keyColumnIndex)) = row
Next
Return index
End Function
Then, you can get the matching DataRow for a given key, like this:
Dim index As Dictionary(Of String, DataRow) = BuildIndex(myDataTable, myKeyColumnIndex)
Dim row As DataRow = Nothing
If index.TryGetValue(myKey, row) Then
' row was found, can now use row variable to access all the data in that row
Else
' row with that key does not exist
End If
You may also want to look into using either the SortedList or SortedDictionary class. Both of these are implementations of binary trees. It's hard to say which of all of these options is going to be fastest in your particular scenario. It all depends on the type of data, how often the index needs to be re-built, how often you search it, how many rows are in the DataTable, and what you need to do with the found items. The best thing to do would be to try each one in a test case and see which one works best for what you need.
You should use row filter or DataTable.Rows.Find() instead of select (select does not use indexes). Depending on your table structure, specifically if your field in question is indexed (locally), performance of either way should be much faster than looping through all rows. In .NET, a set of fields needs to be a PrimaryKey to become indexed.
If your field is not indexed, I would avoid both select and row filter, because aside from overhead of class complexity, they don't offer compile time check for correctness of your condition. If it's a long one, you may end up spending lots of time debugging it once in a while.
It is always preferable to have your check strictly typed. Having first defined an underlying type, you can also define this helper method, which you can convert to extension method of DataTable class later:
Shared Function CheckValue(myTable As DataTable, columnName As String, searchValue As String) As Boolean
For row As DataRow In myTable.Rows
If row(columnName) = searchValue Then Return True
Next
Return False
End Function
or a more generic version of it:
Shared Function CheckValue(myTable As DataTable, checkFunc As Func(Of DataRow, Boolean)) As Boolean
For Each row As DataRow In myTable.Rows
If checkFunc(row) Then Return True
Next
Return False
End Function
and its usage:
CheckValue(myTable, Function(x) x("myColumn") = "123")
If your row class has MyColumn property of type String, it becomes:
CheckValue(myTable, Function(x) x.myColumn = "123")
One of the benefits of above approach is that you are able to feed calculated fields into your check condition, since myColumn here does not need to match a physical myColumn in the table/database.
bool exists = dt.AsEnumerable().Where(c => c.Field<string>("Author").Equals("your lookup value")).Count() > 0;

How to use TypedDataTable.Rows.Find(key as object) to find a row which has a composite key?

I have a TypedDataTable called CamerasDT which has a composite Primary Key of GroupId and CameraId. I want to use TypedDataTable.Rows.Find(key as object) to return a specific row by GroupId and CameraId. I don't seem to be able to find a way to send primary key to the find function. Any help is appreciated.
Use the one of the overloads for the Find method to pass an array of Objects that corresponds to the primary key values you're searching for.
Example from the MSDN article I linked:
The following example uses the values of an array to find a specific
row in a collection of DataRow objects. The method assumes that a
DataTable exists with three primary key columns. After creating an
array of the values, the code uses the Find method with the array to
get the particular object that you want.
Private Sub FindInMultiPKey(ByVal table As DataTable)
' Create an array for the key values to find.
Dim findTheseVals(2) As Object
' Set the values of the keys to find.
findTheseVals(0) = "John"
findTheseVals(1) = "Smith"
findTheseVals(2) = "5 Main St."
Dim foundRow As DataRow = table.Rows.Find(findTheseVals)
' Display column 1 of the found row.
If Not (foundRow Is Nothing) Then
Console.WriteLine(foundRow(1).ToString())
End If
End Sub
In your case you'd pass an Object array with values to search for in your GroupId and CameraId fields.