How to define a Visual Basic dictionary with multiple keys
By definition, a Visual Basic dictionary represents a collection of keys and values. With a little coding, we can define our dictionary to use a multiple value key. A Visual Basic dictionary with multiple keys works great for organizing data where multiple keys are needed. Adding to, updating and accessing the dictionary is very simple and fast. Visual Basic dictionaries provide multiple Methods – See Dictionary(Of TKey, TValue) Class for more information.
The following is a pared down Visual Basic (.Net) program example of a multi-key dictionary.
I used this multiple key dictionary on a financial report I worked on. The report needed to collect a decimal value that varied based on a specific set of unique keys. Tracking values with multiple keys is not uncommon and there are several approaches you can take to programmatically track values with multiple keys. I found the use of a Visual Basic dictionary to be perfect for the task. In our example we’re going to cover constructing the dictionary, constructing the key set, comparing the key set for a match, adding to the dictionary, updating the dictionary, removing an item from the dictionary and lastly looping through the dictionary.
The following class defines the key structure. In this example, PPDKey is made up of 6 values. The functions Equals() and GetHashCode() are overridden for key matching.
Public Class PPDKey Public ppd_Column As Integer Public ppd_FacNum As Integer Public ppd_Section As String Public ppd_Unit As String Public ppd_Level As String Public ppd_Type As String ' override equals for dictionary key (as object) comparison Public Overrides Function Equals(ByVal obj As Object) As Boolean Dim comparedObj As PPDKey = TryCast(obj, PPDKey) If comparedObj Is Nothing Then Return False End If Return (comparedObj.ppd_Column = ppd_Column) And (comparedObj.ppd_FacNum = ppd_Column) And (comparedObj.ppd_Section = ppd_Section) And (comparedObj.ppd_Unit = ppd_Unit) And (comparedObj.ppd_Level = ppd_Level) And (comparedObj.ppd_Type = ppd_Type) End Function ' override GetHashCode for dictionary key (as object) comparison Public Overrides Function GetHashCode() As Integer Return ppd_Column.GetHashCode Xor ppd_FacNum.GetHashCode Xor ppd_Section.GetHashCode Xor ppd_Unit.GetHashCode Xor ppd_Level.GetHashCode Xor ppd_Type.GetHashCode End Function End Class
The following class is a simplified example use of the Visual Basic dictionary. First, we construct the dictionary indicating our multi-key object PPDkey will be used as the dictionary key and we’ll be tracking a decimal value within our dictionary. Next, we loop through a dataset and populate the dictionary with values from the dataset. Next, I’ve provided an example of how to remove an item from the dictionary. Finally, we loop through the dictionary to build a total for a specific single key value. Obviously, we don’t need the dictionary for our example as the total could have been built from the dataset. This is merely an example to show how the dictionary is populated and how it can be accessed either by a specific key or through a for each loop.
Partial Public Class SomeClass ' populate the dictionary Dim dctPPDTotals As New Dictionary(Of PPDKey, Decimal) Dim ds As DataSet = GetRecords() ' sample data set for example purposes For Each dr As DataRow In ds.Tables(0).Rows Dim PPDKey As New PPDKey PPDKey.ppd_Column = CShort(dr.Item("Column").ToString) PPDKey.ppd_FacNum = CShort(dr.Item("FacNum").ToString) PPDKey.ppd_Section = dr.Item("Section").ToString PPDKey.ppd_Unit = dr.Item("Unit").ToString PPDKey.ppd_Level = dr.Item("Level").ToString PPDKey.ppd_Type = dr.Item("Type").ToString ' accumulate total If dctPPDTotals.ContainsKey(PPDKey) Then dctPPDTotals(PPDKey) += CDec(dr.Item("Amount").ToString) Else dctPPDTotals.Add(PPDKey, CDec(dr.Item("Amount").ToString)) End If Next ' remove a specific key PPDKey.ppd_Column = 1 PPDKey.ppd_FacNum = 2 PPDKey.ppd_Section = "A" PPDKey.ppd_Unit = "B" PPDKey.ppd_Level = "C" PPDKey.ppd_Type = "D" If dctPPDTotals.ContainsKey(PPDKey) Then dctPPDTotals.Remove(PPDKey) End If ' get the total for facility 2 Dim decPPDTotal As Decimal = 0 For Each kv In dctPPDTotals If kv.Key.ppd_FacNum = 2 Then decPPDTotal += kv.Value End If Next End Class
References
TryCast Operator
ValueType.GetHashCode Method ()
Xor Operator
Dictionary(Of TKey, TValue) Class
DataSet Class
DataRow Class
For Each…Next Statement