best way to implement 450 switch cases keeping performance in mind - vb.net

I have some hard-coded values for Switch case (and one case have 4 to 5 elements to be added in a list object) and the case statement is 450 + times.
I don't want to implement this by using switch case(actually increasing the length of code ) .
Here is sample code :
Case Set = "A"
obj.Add("1")
obj.Add("2")
obj.Add("3")
obj.Add("4")
obj.Add("5")
Case Set = "B"
obj.Add("66")
obj.Add("77")
Case Set = "C"
obj.Add("888")
obj.Add("999")
obj.Add("111")
Every case statement is different and the elements inside the case is different
My product in Windows product and using vb.net .
Any other alternate way to achieve this .
Suggestions are most welcome!!!!!

You can create a Dictionary(of String, List(of String)). The Key of the dictionary is "A", "B", "C" and the List contains the element you want to add.
Dim dic As New Dictionary(of String, List(of String))
dic.add("A", new List(of String)({"1", "2"}))
dic.add("B", new List(of String)({"66", "77"}))
later you can just do this:
Dim key As String = "A"
obj.addRange(dic(key))
If you want to remove the static dictionary creation, you can easily build up the dictionary based on a file or database.

Related

Why does ".Remove" affect all the items in a 2D structure assigned with a list?

I'm currently trying to create a Sudoku Solver, and on the step of assigning some possible values to a box that is not already preoccupied. (Bit of background info for why I'm doing this shebang: Sudoku is a number game based on a 9x9 grid, its contextual rules allow certain boxes in the grid that are not preoccupied to hold possible values during the process of solving )
To do this I created a structure, defined it as two dimensional, and populated it with a predefined list of integers using a for-loop.
Now when I tried to remove one integer from the list of a particular item in the two dimensional structure, I found out that all the lists of the items in the structure have had that integer removed. There's probably a simple solution to this, but I've been really struggling to find it. Hope the code below clarifies the somewhat confusing verbal explanation.
Structure Element
Dim PossibleValues As List(Of Integer)
Dim ElementValue As Integer
End Structure
Sub Main()
Dim List as New List(Of Integer)({1,2,3})
Dim TDP(8,8) as Element
For x as integer = 0 to 8
For y as integer = 0 to 8
TDP(x,y).PossibleValues = List
Next
Next
TDP(0,0).PossibleValues.Remove(1)
End Sub
Now I expect only TDP(0,0) would have a list of "2,3" when print out its list of integers, but when I check other items , i.e. TDP(1,0), its list is of integer is also "2,3"
Look at the assignment here:
TDP(x,y).PossibleValues = List
List(Of T) is a reference type, so this assigns a reference to the same List object to each of the array elements.
If you want each item to have it's own list of possible items, you need to either deep copy the list or create a new list:
Sub Main()
Dim TDP(8,8) as Element
For x as integer = 0 to 8
For y as integer = 0 to 8
TDP(x,y).PossibleValues = New List(Of Integer)({1,2,3})
Next
Next
TDP(0,0).PossibleValues.Remove(1)
End Sub

For each in double list

Is it possible to do a for each joining two list and browse through the new "duo list" ?
something like :
For Each elm In list1 Join list2
elm.obj1 // objet with list1 type
elm.obj2 // object with list2 type
next elm
Lists have the same length.
You can join by index with LINQ's Enumerable.Zip and create an anonymous type:
Dim zipped = list1.Zip(list2, Function(obj1, obj2) New With {Key obj1, Key obj2})
For Each pair In zipped
Console.WriteLine(pair.obj1)
Console.WriteLine(pair.obj2)
Next
Note that zipped is not a collection yet but a query. Whenever you will enumerate it(f.e. with For Each, First, ToList etc.) you will execute this query again. If you need to persist it you can create a list or array(ToList/ToArray) and access this instead.
The lazy evaluation of many LINQ methods is called Deferred Execution.
If you mean that you want to enumerate a single, combined list then you would do this:
For Each item In list1.Concat(list2)
'Use item here.
Next
If what you actually mean is that you want to access the items in both lists at the same index at the same time then how would a For Each loop make sense? In that case you'd use a For loop and get both items by index:
For i = 0 To list1.Count - 1
Dim item1 = list1(i)
Dim item2 = list2(i)
'Use item1 and item2 here.
Next
Taking into account the Zip method used in the other answer and combining it with my Tuple suggestion:
For Each tpl In list1.Zip(list2, Function(a, b) AddressOf Tuple.Create)
Console.WriteLine(tpl.Item1)
Console.WriteLine(tpl.Item2)
Next

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.

vb.net Pair Combinations to Create All Possible Sets

I need help figuring out how to go about programming this problem. I have an unknown number of pairs. Each pair is a Length x Width. I want to create sets of every possible combination of either a Length or Width from each pair. Here is an example of what I'm trying to do:
If I input 3 pairs, (1x2) (3x4) (5x6) I would get the following sets:
(1,3,5) (1,3,6) (1,4,5) (1,4,6) (2,3,5) (2,3,6) (2,4,5) (2,4,6)
So if I had 4 pairs, it would create a total of 16 sets, etc. I need to be able to input each pair and after all pairs have been entered, I need it to print out the sets. It can never include both numbers from a given pair in the same set. How do I create a loop or is there a built in math function that could produce all possible sets from a given number of pair inputs? I hope I described the problem well enough but if not, please ask questions. Thanks
This is called Cartesian product.
For example, if we have two sets A and B, such that
A = {1,2}
B = {3,4}
Then the result of the Cartesian product A x B is equal to
A x B = {(1,3),(1,4),(2,3),(2,4)}
If now we want to make the Cartesian product between the result obtained above and a new set, for example:
N = {5,6}
The result of the Cartesian product A x B x N, is equal to
A x B = {(1,3),(1,4),(2,3),(2,4)}
N = {5,6}
──────────────────────────────────────────────────
A x B x N = {(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)}
Each element of the first set must be paired with each element of the second set.
I have developed 4 solutions to the Cartesian product:
Using a mathematical model, but without recursion. This solution
vectors using calculating for each combination number.
Using recursion, with the Collections class.
using the List (Of ...) class, also with recursion.
These three solutions seemed to me difficult to explain to you.
Furthermore, it is very difficult for me to explain my thoughts in English, because my native language is Castilian.
So I made the effort to create another solution that does not use recursion, which was more simple and friendly for any programmer.
Finally, I could create a satisfactory solution. Easy to understand and without recursion.
It is also very versatile. Any number of sets is accepted, as required, from 2 onwards.
You can also use any number of items. This depends on the requirements of each developer.
I hope this 4th. solution I devised, will please you, esteemed colleagues.
Only need a ListBox1 within Form4. Here it is:
Public Class Form4
Private Sub Form4_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'┌─────────── Temporary code for example ───────────┐
Dim Set_1 As List(Of String) = New List(Of String)
Dim Set_2 As List(Of String) = New List(Of String)
Dim Set_3 As List(Of String) = New List(Of String)
Set_1.Add("1")
Set_1.Add("2")
Set_2.Add("3")
Set_2.Add("4")
Set_3.Add("5")
Set_3.Add("6")
'└──────────────────────────────────────────────────┘
Dim Sets As List(Of Object) = New List(Of Object)
Sets.Add(Set_1)
Sets.Add(Set_2)
Sets.Add(Set_3)
Dim product As List(Of String) = Sets(0)
For i = 1 To Sets.Count - 1
product = CartesianProduct(product, Sets(i))
Next
For Each element As String In product
Me.ListBox1.Items.Add(element)
Next
End Sub
Private Function CartesianProduct(ByVal Set_A As List(Of String), ByVal Set_B As List(Of String)) As List(Of String)
Dim product As List(Of String) = New List(Of String)
For Each a As String In Set_A
For Each b As String In Set_B
product.Add(a & b)
Next
Next
Return product
End Function
End Class
Have a nice day! :)

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;