Introduction

Dictionaries are collections that use keys to locate values. When you look up a particular key, the dictionary will return the associated value. I recently had a requirement to make several lists(Of String) available at different times during the application’s life cycle. Although I could have simply created a separate List(of String) with it’s own name for each set of data, this meant that I had to fiddle around more than I wanted to get the correct list name for the list I wanted at any one time. As it happened, each list contained words all of the same length. In this scenario, a Dictionary is ideal because the key can be the word length and the value can be the List of Strings of that length.

Creating the Dictionary

In the cut-down sample I’ll use for this post, the dictionary will be used to hold words of 3, 4 or 5 letters. So I’ll create a Dictionary(Of Integer, List(Of String). What that means is that the Dictionary will use Integers as the Keys to locate Lists Of Strings (which are the Values). As I explained at the start, Dictionaries work with key/value pairs. I’ve chosen to use List(Of String) because it suits my purposes, but in other projects the type of the Value might be just about anything – a String, a Control type, objects of the MyCars class - whatever you want to store and access.

Here’s the code that creates the Dictionary and adds three Keys:

1 2 3 4 5 6 7 8 9 Dim InMemoryWords As New Dictionary( Of Integer , List( Of String )) Private Sub Form1_Load(sender As Object , e As System.EventArgs) Handles Me .Load ' Set up the in-memory collections For i As Integer = 3 To 5 InMemoryWords.Add(i, New List( Of String )) Next End Sub

You can see that the Dictionary is named InMemoryWords and in the form load event I have added three keys with the values 3, 4 and 5 respectively. At this point each of those keys points to a separate List(Of String), but all the lists are empty.

I’ll spin up some sample lists just for this example. In a production application, you’d probably get the strings from a text file or other data source. Just for completeness, here is the method that generates the sample words:

1 2 3 4 5 6 7 8 9 Private Sub GenerateSampleWords() InMemoryWords(3).AddRange( New String () { "tea" , "pot" , "tie" , "hot" , "too" , "toe" , "pit" , "tip" }) InMemoryWords(4).AddRange( New String () { "teas" , "pots" , "tied" , "spot" , "spit" , "tale" , "take" }) InMemoryWords(5).AddRange( New String () { "taste" , "paste" , "tired" , "spots" , "spite" , "tales" , "taken" }) End Sub

If I call the GenerateSampleWords method as the next step in the Form Load event, the Dictionary will be fully populated.

1 2 3 4 5 6 7 8 Private Sub Form1_Load(sender As Object , e As System.EventArgs) Handles Me .Load ' Set up the in-memory collections For i As Integer = 3 To 5 InMemoryWords.Add(i, New List( Of String )) Next GenerateSampleWords() End Sub

So at this stage each element of the Dictionary contains an integer key and a List(Of String) value. Each list contains some words. I’ve chosen to store three letter words against the key of 3, four letter words against the key of 4 and five letter words against the key of 5, but of course you can store whatever strings you like in those lists – that is, the Dictionary does not limit you to those word lengths.

Displaying Content

I’ll add a ListBox to the Windows Form that I’m using for this example. That way we can quickly check the content of some of the Dictionary elements. I’ll extract the value of the element that has the key of 4 and display the contents of this list in the list box:

1 2 3 4 5 6 7 8 9 10 11 12 Private Sub Form1_Load(sender As Object , e As System.EventArgs) Handles Me .Load ' Set up the in-memory collections For i As Integer = 3 To 5 InMemoryWords.Add(i, New List( Of String )) Next GenerateSampleWords() For Each Str As String In InMemoryWords(4) ListBox1.Items.Add(Str) Next End Sub

As you’d expect, the result will be:

Adding or Removing from Values at Run Time

How you use this dictionary will depend on what your application needs it for. Really, I only wanted this post to make it easy to understand how to create a dictionary that probably looks complicated when you first see it. And I’ve done that (at least I hope I have!). But as we’re here now, I may as well play around with the dictionary in a couple of ways, so you can see possible ways you might use it.

Although I assigned values to the Lists at the start, it’s very easy to add or remove strings from any of the lists. Just as an example, take a look at this:

' Add a new string to element 4 InMemoryWords(4).Add( "cool" ) ListBox1.Items.Clear() For Each Str As String In InMemoryWords(4) ListBox1.Items.Add(Str) Next

This code adds a new string to the element that has a key of 4. The displayed list now has the additional word included in its content:

You can remove individual strings by their index number or text value, and can remove a range of strings, or all of them. That is, you can manipulate these Lists of String just as you would any other single list.

Swapping Values at Run Time

If you have different sets of strings that you want to swap in and out of the Lists in the Dictionary, this also is very easy to do.

1 2 3 4 5 6 7 8 9 10 11 ' Manual build of new list Dim MyList As New List( Of String ) MyList.Add( "goat" ) MyList.Add( "gets" ) MyList.Add( "beat" ) InMemoryWords(4) = MyList ListBox1.Items.Clear() For Each Str As String In InMemoryWords(4) ListBox1.Items.Add(Str) Next

The first few lines of code create a new List(Of String) and populate it. Line 7 assigns that list as the value of the element of the Dictionary that has the key of 4. The remaining lines display the result:

Searching for Strings

Finally, I thought you may find it interesting to see how easy it is to search the dictionary. I’ve added a TextBox named txtInput and used the word “take” as its text:

Using the following code, I can search the entire dictionary to see if that word – take – is stored there:

1 2 3 4 5 For i As Integer = 3 To 5 If InMemoryWords(i).Contains(txtInput.Text) Then MessageBox.Show( "target word - " & txtInput.Text & " - found in dictionary" ) End If Next

It is – we know it is, because it’s showing in the list box, so when this code runs, the message box will appear and confirm.

Actually, if you’ve followed this all the way through, you may have spotted that I can improve that search code. In the real world application where there are tens of thousands of words in each list, it’s a waste of processing power and time to go through every element in the dictionary. We can simply target the element that contains the words of the length of our search word – in this case the four letter word ‘take’.

Here’s the code:

1 2 3 4 ' Quicker, making better use of the keys: If InMemoryWords(txtInput.Text.Length).Contains(txtInput.Text) Then MessageBox.Show( "target word - " & txtInput.Text & " - found in dictionary" ) End If

This time there’s no loop; I’ve directly targeted the element whose key equates to the length of the target word – i.e. InMemoryWords(4). Although you wouldn’t see a difference here, this version will be substantially faster than the previous one once the number of strings increases.

Posted May 05 2014, 06:40 PM by Ged Mead