Store a two value combination - vb.net

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.

Related

How to get index with known value as string in arraylist?

I have ArrayList with multi dimensional values in Structure as ArrayList
Structure
(0)=> Mstructure.ABCD
Area (these are value of ABCD)
Name
(1)=> Mstructure.EFGH
Area
Name
I want to know the index of string ABCD.
I tried
Dim myIndex as Integer = Structure.IndexOf("ABCD")
Dim myIndex = Array.IndexOf(Structure.ToArray(), myString)
This returned only -1. I want to get 0 if string is ABCD
EDITED
Structure is defined as ArrayList. I can iterate over it if I use loop e.g
Structure(i).GetType().Name = "ABCD"
I have checked if it exists in the ArrayList
Dim result = Structure.ToArray().Any(Function(x) x.ToString().Contains("ABCD"))
But I want to know the index of the multidimensional ArrayList without looping it. I want to get the index of Mstructure.ABCD. Msttructure.ABCD has values inside it but without knowing those values I want to get the index value.
(0){Mstructure.ABCD}
(1){Mstructure.EFGH}
(2){Mstructure.IJKL}
hhmmm i would use collections instead, or create an object with multi collections to make it easier for me... Have you thought of that?

Finding lowest value in List of tuple in VB.Net

I am trying to find lowest Item2 and return Item1 from tuple list, I tried to do it with List.Min but I couldn't get it right, here is my code.
Dim ahlist As New List(Of Tuple(Of String, Double))
ahlist.Add(Tuple.Create("test1", 1.2))
ahlist.Add(Tuple.Create("test2", 0.2))
ahlist.Add(Tuple.Create("test3", 1.8))
Basically I want to find lowest number and return string (test2) in this case.
I'd recommend using a different data structure for this:
https://msdn.microsoft.com/en-us/library/ms132329(v=vs.110).aspx
You add the key/value combinations. The 0th one in the list is always the minimum key, making its an O(1) operation instead of O(n). In this case, the key would be the Decimal, and the value would be the string.
You can reverse the order of the items for the comparison to be by the number first:
Dim ahlist As New List(Of Tuple(Of Double, String))
ahlist.Add(Tuple.Create(1.2, "test1"))
Just a simple fix from C# syntax to VB.net to #Aamir Nakehwa's answer.
Dim minValue As Double = ahlist.Min(Function(x) x.Item2)
Debug.Print(minValue.ToString)
ahlist.Min(x => x.Item2)
Try this. I will return you the minimum value from your tuple list.
And hold it in any variable to use like below
Dim minValue as Double = ahlist.Min(Function(x) x.Item2)

Create a dictionary out of a list vb.net

i have a list with 2 columns (clm1=StoreID and clmn2=ProductID).
i need to loop through this list and create a dictionary(StoreID , List(of ProductID))
i am using vb.net . can you please help me with the loop i have to make?
The list data is something like
StoreID ProductID
1 234
2 456
1 222
3 768
1 100
9 876
e.t.c.
I assume that your data is stored somewhat like this:
Structure Item
Public StoreID As Integer
Public ProductID As Integer
End Structure
Dim l As List(Of Item)
Then you have two options. The first one is to create the dictionary by hand:
Dim dictionary As New Dictionary(Of Integer, List(Of Integer))
For Each item As Item In l
Dim subList As List(Of Integer)
Dim keyExists = dictionary.TryGetValue(item.StoreID, subList)
If keyExists Then
subList.Add(item.ProductID)
Else
subList = New List(Of Integer)
subList.Add(item.ProductID)
dictionary.Add(item.StoreID, subList)
End If
Next
Here, you just iterate all items. Check the dictionary if it already contains an entry for the store id. If so, just add the product id. If not, create an entry and then add the product id.
If you're not overly concerned with performance, you can use the following LINQ expression to create the dictionary:
Dim dictionary = l.GroupBy(Function(item) item.StoreID) _
.ToDictionary(Function(group) group.Key, _
Function(group) group.Select(Function(item) item.ProductID) _
.ToList())
You first group the elements by their StoreID. Then, the ToDictionary() method creates the dictionary. It takes two parameters. The first one is a function that specifies the key of each element. In this case, we want to use the group's key as the dictionary key (which is the store id). The second parameter is the value that is inserted in the dictionary. First, we use Select to map each Item to its ProductID (because we want to store product ids and not entire items. Then we call ToList() to generate a list from the items in the group.

Group Dictionary values of a particular key

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

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;