Introduction to Dictionaries

Description

A dictionary is a list of items with the following two rules:

In some cases, in addition to these two rules, the items should - in some cases must - be ordered. To order the items, the keys are used. Because in most cases a dictionary is made of words, the keys are ordered in alphabetical order. A dictionary can also be made of items whose keys are date values. In this case, the items would be ordered in chronological order.

There are various types of dictionary types of list used in daily life. The word "dictionary" here does not imply the traditional dictionary that holds the words and their meanings in the English language. The concept is applied in various scenarios.

Practical LearningPractical Learning: Introducing Geometric Accessories

  1. Start Microsoft Visual Studio
  2. Create a Windows Forms App named Exercise7

The .NET Support for Dictionary-Based Lists

To support dictionary-based lists, the .NET Framework provides various interfaces and classes. The interfaces allow you to create your own dictionary type of collection class. The classes allow you to directly create a dictionary-based list with an already built-in functionality. One way the NET Framework provides support for dictionary-based collections is through two regular classes: Hashtable and SortedList. Both classes implement:

The .NET Framework also provides dictionary-types through regular and generic classes. From the System.Collections.Generic namespace, to create a dictionary type of collection, you can use either the Dictionary<>, the SortedDictionary<>, or the SortedList<> classes. The System.Collections.Generic.Dictionary<> class is equivalent to the System.Collections.Hashtable class. The System.Collections.Generic.SortedList<> class is equivalent to the System.Collections.SortedList class. The System.Collections.Generic.SortedDictionary<> class is equivalent to the System.Collections.Generic.SortedList<> class with some differences in the way both classes deal with memory management.

Creating a Dictionary

Introduction

To start a dictionary-based list, you can declare a variable of the dictionary class of your choice. You can do this with the Hashtable class. Here is an example:

using System.Collections;

namespace SchoolManagement
{
    public class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        void InitializeComponent()
        {
        }

        void Exercise_Load(object sender, EventArgs e)
        {
            Hashtable Students = new Hashtable();
        }
    }
}

If you decide to use either the System.Collections.Generic.Dictionary<>, the System.Collections.Generic.SortedDictionary<>, or the System.Collections.Generic.SortedList<> class, when declaring the variable, you must specify the parameter types (the names of the data types or classes in the <> operator).

Index Assignment

There are various ways you can specify the values or objects of a dictionary. Like most classes, a dictionary is organized like an array. This means that, in this case, every item has an index, but the index is the key of the item. Based on this, using the name of the variable of the dictionary, you can access an item by its index and assign the desired value to it. Here are examples:

namespace Dictionaries
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            // Dictionay: the key is a int integer, the value is a string
            Dictionary<int, string> instruments = new Dictionary<int, string>();

            instruments[759240] = "6-String Semi-Hollow-Body Electric Guitar";
            instruments[184920] = "Size 4/4 (Full Size), Black Solid Wood-Flamed, 1-Piece Violin";
            instruments[824083] = "88-Key Weighted Action Synthesizer";
            instruments[302805] = "Rumble 25 V3 Bass Amplifier";

            // Sorted Dictionay: the key is a string, the value is a decimal number with single precision
            SortedDictionary<string, float> elements = new SortedDictionary<string, float>();

            elements["Hydrogen"] = 1.008f;
            elements["Helium"] = 4.0026f;
            elements["Lithium"] = 6.94f;
            elements["Beryllium"] = 9.0122f;
            elements["Boron"] = 10.81f;
            elements["Carbon"] = 12.011f;

            // Sorted List: the key is a single character, the value is a string
            SortedList<char, string> bricks = new SortedList<char, string>();

            bricks['c'] = "Concrete Bricks";
            bricks['s'] = "Sun-Dried Clay Bricks ";
            bricks['b'] = "Burnt Clay Bricks";
            bricks['l'] = "Sand Lime Bricks";
            bricks['a'] = "Fly Ash Bricks";
            bricks['e'] = "Engineering Bricks";
        }
    }
}

Initializing a Dictionary Object

If you declare a Dictionary<>, a SortedDictionary<>, or a SortedList<> variable, before its semicolon, open some curly brackets {}. Inside the brackets, for each item, create some square brackets as done for an array. In those square brackets, enther the key of the new item. Outside the square brackets, assign the value to the item. Repeat for each item. Separate them with comas. Here are examples:

namespace Dictionaries
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            // Dictionay: the key is an integer, the value is a string
            Dictionary<int, string> instruments = new Dictionary<int, string>()
            {
                [759240] = "6-String Semi-Hollow-Body Electric Guitar",
                [184920] = "Size 4/4 (Full Size), Black Solid Wood-Flamed, 1-Piece Violin",
                [824083] = "88-Key Weighted Action Synthesizer",
                [302805] = "Rumble 25 V3 Bass Amplifier",
            };

            // Sorted Dictionay: the key is a string, the value is a decimal number with single precision
            SortedDictionary<string, float> instruments2 = new SortedDictionary<string, float>()
            {
                ["Hydrogen"]  = 1.008f,
                ["Helium"]    = 4.0026f,
                ["Lithium"]   = 6.94f,
                ["Beryllium"] = 9.0122f,
                ["Boron"]     = 10.81f,
                ["Carbon"]    = 12.011f
            };

            // Sorted List: the key is a single character, the value is a string
            SortedList<char, string> bricks = new SortedList<char, string>()
            {
                ['c'] = "Concrete Bricks",
                ['s'] = "Sun-Dried Clay Bricks ",
                ['b'] = "Burnt Clay Bricks",
                ['l'] = "Sand Lime Bricks",
                ['a'] = "Fly Ash Bricks",
                ['e'] = "Engineering Bricks"
            };
        }
    }
}

Adding Items to the Collection

The classic way to create a list is to add items to it. To let you add an item to its list, the System.Collections.Hashtable, the System.Collections.Generic.Dictionary<TKey,TValue>, the System.Collections.Generic.SortedDictionary<TKey,TValue>.Add(), and the System.Collections.SortedList<TKey,TValue> classes are equipped with a method named Add. The syntax for the System.Collections.Hashtable.Add() method is:

public virtual void Add(object Key, object? Value);

As you can see, you must provide the key and the value as the first and second arguments to the method respectively. Here are examples of calling the System.Collections.Hashtable.Add() method:

void Exercise_Load(object sender, EventArgs e)
{
    Hashtable Students = new Hashtable();

    Students.Add("Hermine", "Tolston");
    Students.Add("Patrick", "Donley");
}

The syntax for the System.Collections.Generic.Dictionary<TKey,TValue>.Add(), the System.Collections.Generic.SortedDictionary<TKey,TValue>.Add(), and the System.Collections.Generic.SortedList<TKey,TValue>.Add() method is:

public void Add(TKey key, TValue value);

Trying to Add an Item

When calling the Add() method, you must provide a valid Key argument: it cannot be null. For example, the following code would produce an error:

void Exercise_Load(object sender, EventArgs e)
{
    Hashtable Students = new Hashtable();

    Students.Add("Hermine", "Tolston");
    Students.Add("Patrick", "Donley");
    Students.Add(null, "Hannovers");
}

This would produce:

When adding the items to the list, as mentioned in our introduction, each key must be unique: you cannot have two exact keys. If you try adding a key that exists already in the list, the compiler would throw an ArgumentException exception. Based on this, the following code would not work because, on the 4th call, a "938403" key exists already:

namespace Dictionaries
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            Hashtable Students = new Hashtable();

            students.Add(283857, "Hermine Tolston");
            students.Add(938403, "Patrick Donley");
            students.Add(749725, "Chrissie Hannovers");
            students.Add(938403, "Patrick Herzog");
        }
    }
}

This would produce:

As one solution to this problem, if the dictionary is created in your application by the user, you should (must) define a scheme that would make sure that each key is unique among the other keys in the list. As another and probably better solution, declare your variable with the System.Collections.Generic.Dictionary<TKey,TValue> class. The class is equipped with a method named TryAdd. Its syntax is:

public bool TryAdd(TKey key, TValue value);

This method takes the same argument as Add(). Here is an example of calling it:

namespace Dictionaries
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            Dictionary<long, string> students = new();

            students.TryAdd(283857, "Hermine Tolston");
            students.TryAdd(938403, "Patrick Donley");
            students.TryAdd(749725, "Chrissie Hannovers");
            students.TryAdd(938403, "Patrick Herzog");
        }
    }
}

When this method is called, if the compiler finds out that the key passed as argument exists already, the item would not be added to the dictionary and no exception would be thrown.

Accessing the Items of a Dictionary-Type of List

Accessing an Item by its Index

Remember that a dictionary is array like an array where each item is an indexed property. Therefore, to access an item, you can type the name of the dictionary variable followe by square brackets. In the square brackets, type the name of the key. This operation produces the value> of the item. Here are examples:

namespace Dictionaries
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            // Dictionay: the key is a int integer, the value is a string
            Dictionary<int, string> instruments = new Dictionary<int, string>();

            instruments[759240] = "6-String Semi-Hollow-Body Electric Guitar";
            instruments[184920] = "Size 4/4 (Full Size), Black Solid Wood-Flamed, 1-Piece Violin";
            instruments[824083] = "88-Key Weighted Action Synthesizer";
            instruments[302805] = "Rumble 25 V3 Bass Amplifier";

            lbxInstruments.Items.Add(instruments[759240]);
            lbxInstruments.Items.Add(instruments[184920]);
            lbxInstruments.Items.Add(instruments[824083]);
            lbxInstruments.Items.Add(instruments[302805]);

            // Sorted Dictionay: the key is a string, the value also is a string
            SortedDictionary<string, string> elements = new SortedDictionary<string, string>();

            elements["H"] = "Hydrogen";
            elements["He"] = "Helium";
            elements["Li"] = "Lithium";
            elements["Be"] = "Beryllium";
            elements["B"] = "Boron";
            elements["C"] = "Carbon";

            lbxElements.Items.Add(elements["H"]);
            lbxElements.Items.Add(elements["He"]);
            lbxElements.Items.Add(elements["Li"]);
            lbxElements.Items.Add(elements["Be"]);
            lbxElements.Items.Add(elements["B"]);
            lbxElements.Items.Add(elements["C"]);

            // Sorted List: the key is a single character, the value is a string
            SortedList<char, string> bricks = new SortedList<char, string>();

            bricks['c'] = "Concrete Bricks";
            bricks['s'] = "Sun-Dried Clay Bricks ";
            bricks['b'] = "Burnt Clay Bricks";
            bricks['l'] = "Sand Lime Bricks";
            bricks['a'] = "Fly Ash Bricks";
            bricks['e'] = "Engineering Bricks";

            lbxBricks.Items.Add(bricks['c']);
            lbxBricks.Items.Add(bricks['s']);
            lbxBricks.Items.Add(bricks['b']);
            lbxBricks.Items.Add(bricks['l']);
            lbxBricks.Items.Add(bricks['a']);
            lbxBricks.Items.Add(bricks['e']);
        }
    }
}

This would produce:

Accessing a Dictionary Item by its Index

Entering a Dictionary

Although, or because, the key and value combination of a dictionary are distinct, to consider their combination as a single object, if you are using either the System.Collections.Hasthtable or the System.Collections.SortedList class, the .NET Framework provides a structure named DictionaryEntry. To access an item, you can use the foreach loop to visit each item.

To support the foreach loop, the System.Collections.Hashtable and the System.Collections.SortedList classes implement the IEnumerable.GetEnumerator() method. In this case, the item is of type DictionaryEntry: it contains a key and a value in combination.

The DictionaryEntry structure contains two properties named Key and Value to identify the components of a combination. Here is an example:

using System.Collections;

namespace RedOakHighSchool
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            Hashtable students = new Hashtable();

            students.Add("Hermine", "Tolston");
            students.Add("Patrick", "Donley");
            students.Add("Chrissie", "Hannovers");
            students.Add("Patricia", "Herzog");
            students["Michael"] = "Herlander";

            foreach (DictionaryEntry entry in students)
                lbxStudents.Items.Add(entry.Key + " " + entry.Value);
        }
    }
}

This would produce:

If you are using a generic class, the .NET Framework provides a read-only structure named KeyValuePair<>. That structure follows the same functionality as the System.Collections.DictionaryEntry structure, except that you must apply the rules of generic classes.

The Hashtable/SortedList and the Dictionary/SortedList Difference

If you use the System.Collections.Hashtable or the System.Collections.Generic.Dictionary<> class to create your list, the items are cumulatively added to the collection every time you call the Add() method of your chosen class or when you use the indexed property to add an item. In our introduction, we saw that the optional third rule of a dictionary type of list is that the list be sorted based on the key. To spare you the hassle of manually taking care of this, the alternative is to use the SortedList class.

Whenever a new item is added to a System.Collections.SortedList variable, a System.Collections.Generic.SortedDictionary<> variable, or a System.Collections.Generic.SortedList<> variable, the list is rearranged so the collection can be sorted in either alphabetical or chronological order based on the keys. This means that, if you want your list to be logically arranged by the keys, use one of these Sorted classes to create your dictionary.

The Keys and the Values of a Collection

After adding one or more items to the list, they are stored in two collections. The keys are stored in a collection represented by a property named Keys. The values are stored in the Values property. In the System.Collections classes, the Keys and the Values properties are of type ICollection.

To assist you with managing the keys of their collections, the System.Collections.Generic.Dictionary<, >, the System.Collections.Generic.SortedDictionary<, >, and the System.Collections.Generic.SortedList<, > classes are equipped with a nested sealed class named KeyCollection. The KeyCollection class implements the System.Collections.ICollection interface, the ICollection<>, the IEnumerable<>, and the IReadOnlyCollection<> generic interfaces. The only real functionalities of the nested KeyCollection classes are its ability to know the current number of items in the list and the ability to enumerate the members of the collection through a foreach loop.

To assist you with the values of their lists, the System.Collections.Generic.Dictionary<>, the System.Collections.Generic.SortedDictionary<>, and the System.Collections.Generic.SortedList<> classes are equipped with a nested sealed class named ValueCollection. The ValueCollection class implements the System.Collections.ICollection interface, the ICollection<>, the IEnumerable<>, and the IReadOnlyCollection<> generic interfaces. The functionality of the ValueCollection class is the same as its counterpart of the System.Collections namespace.

Checking an Item

Checking the Existence of an Item

Locating an item in a dictionary type of list consists of looking for either a key, a value, or a combination of key=value. The System.Collections.Hashtable, the System.Collections.Generic.Dictionary<, >, and the System.Collections.Generic.SortedList<, > classes are equipped to handle these operations with little effort on your part. If you know the key of an item but want to find a value, you can use the indexed property because it produces it. Here is an example:

void Exercise_Load(object sender, EventArgs e)
{
    Hashtable students = new Hashtable();

    students.Add("Hermine", "Tolston");
    students.Add("Patrick", "Donley");
    students.Add("Chrissie", "Hannovers");
    students.Add("Patricia", "Herzog");
    students["Michael"] = "Herlander";

    foreach (DictionaryEntry entry in students)
        lbxStudents.Items.Add(entry.Key + " " + entry.Value);

    string Value = (string)Students["Chrissie"];
    MessageBox.Show("The value of the Chrissie key is " + Value);
}

This would produce:

Checking Whether a Dictionary Contains a Certan Item

To find out whether a key/value item exists in the list, if you are using one of the classes from the System.Collections namespace, you can call the System.Collections.Hashtable.Contains() or the System.Collections.SortedList.Contains() method. Its syntax is:

public virtual bool Contains(object key);

To look for an item, pass its key as argument to this method. Here is an example:

void Exercise_Load(object sender, EventArgs e)
{
    Hashtable students = new Hashtable();

    students.Add("Hermine", "Tolston");
    students.Add("Patrick", "Donley");
    students.Add("Chrissie", "Hannovers");
    students.Add("Patricia", "Herzog");
    students["Michael"] = "Herlander";

    foreach (DictionaryEntry entry in students)
        lbxStudents.Items.Add(entry.Key + " " + entry.Value);

     bool found = students.Contains("Chrissie");

    if (found == true)
        MessageBox.Show("The list contains an item " +
                        "whose key is Chrissie");
    else
        MessageBox.Show("The list doesn't contain an " +
                        "item whose key is Chrissie");

    found = students.Contains("James");

    if (found == true)
        MessageBox.Show("The list contains an item " +
                        "whose key is James");
    else
        MessageBox.Show("The list doesn't contain an " +
                        "item whose key is James");
}

This would produce:

 

Checking the Existence of a Key

We have seen that the System.Collections.Hashtable.Contains() and the System.Collections.SortedList.Contains() methods allow you to find out whether a collection contains a certain specific key. An alternative is to call a method named ContainsKey.

The syntax of the System.Collections.Hashtable.ContainsKey() and the System.Collections.SortedList.ContainsKey() method is:

public virtual bool ContainsKey(object key);

The syntax of the System.Collections.Generic.Dictionary.ContainsKey() and the System.Collections.Generic.SortedList.ContainsKey() method is:

public bool ContainsKey(TKey key);

Checking the Existence of a Value

To let you find out whether a particular value exists in the list, all dictionary classes are equipped with a method named ContainsValue. The syntax of the System.Collections.Hashtable.ContainsValue() and the System.Collections.SortedList.ContainsValue() method is:

public virtual bool ContainsValue(object key);

The syntax of the System.Collections.Generic.Dictionary<>.ContainsValue(), the System.Collections.Generic.SortedDictionary<>.ContainsValue(), and the System.Collections.Generic.SortedList<>.ContainsValue() method is:

public bool ContainsValue(TKey key);

Getting the Value of a Key

The ContainsKey() method allows you to only find out whether a dictionary-based collection contains a certain key. It does not identify that key and it does not give any significant information about that key, except its existence. In some operations, first you may want to find out whether the collection contains a certain key. Second, if that key exists, you may want to get its corresponding value.

To assist you with both checking the existence of a key and getting its corresponding value, the Dictionary<>, SortedDictionary<>, and SortedList<> generic classes are equipped with a method named TryGetValue. Its syntax is:

public bool TryGetValue(TKey key, out TValue value);

When calling this method, the first argument must be the key to look for. If that key is found, the method returns its corresponding value as the second argument passed as an out reference.

Removing Items From a Dictionary

Remeoving an Item by its Key

To let you delete an item from its list, all dictionary classes are equipped with a method named Remove method. The syntax of the System.Collections.Hashtable and the System.Collections.SortedList method is:

public virtual void Remove(object key);

Here is an example:

using System.Collections;

namespace RedOakHighSchool
{
    public partial class Exercise : Form
    {
        Hashtable? students;

        public Exercise()
        {
            InitializeComponent();
        }

        void Exercise_Load(object sender, EventArgs e)
        {
            students = new Hashtable();

            students.Add("Hermine", "Tolston");
            students.Add("Patrick", "Donley");
            students.Add("Chrissie", "Hannovers");
            students.Add("Patricia", "Herzog");
            students["Michael"] = "Herlander";
            students["Philemon"] = "Jacobs";
            students["Antoinette"] = "Malhoun";

            foreach (DictionaryEntry entry in students)
                lbxStudents.Items.Add(entry.Key + " " + entry.Value);
        }

        void btnRemover_Click(object sender, EventArgs e)
        {
            students!.Remove("Chrissie");

            lbxStudents.Items.Clear();
            
	    foreach (DictionaryEntry entry in Students)
                lbxStudents.Items.Add(entry.Key + " " + entry.Value);
	}
    }
}

This would produce:

The syntax for the System.Collections.Generic.SortedDictionary<>.Remove() and the System.Collections.Generic.SortedList<>.Remove() method is:

public bool Remove(TKey key);

The System.Collections.Generic.Dictionary<> class is equipped with the Remove() method that is overloaded with two versions. The syntax of one of the versions is:

public bool Remove(TKey key);

The syntax of the other version of the System.Collections.Generic.Dictionary.Remove()<> method is:

public bool Remove (TKey key, out TValue value);

Remeoving all Items from a Dictionary

To let you delete all items from its list, all dictionary classes contain a method named Clear(). Its syntax is:

public virtual void Clear();

This method delete all items from the dictionary held by its variable. Here is an example of calling it:

using System.Collections;

namespace RedOakHighSchool
{
    public partial class Exercise : Form
    {
        Hashtable? students;

        public Exercise()
        {
            InitializeComponent();
        }

        void Exercise_Load(object sender, EventArgs e)
        {
            students = new Hashtable();

            students.Add("Hermine", "Tolston");
            students.Add("Patrick", "Donley");
            students.Add("Chrissie", "Hannovers");
            students.Add("Patricia", "Herzog");
            students["Michael"] = "Herlander";
            students["Philemon"] = "Jacobs";
            students["Antoinette"] = "Malhoun";

            foreach (DictionaryEntry entry in students)
                lbxStudents.Items.Add(entry.Key + " " + entry.Value);
        }

        void btnRemover_Click(object sender, EventArgs e)
        {
            students!.Clear();

            lbxStudents.Items.Clear();
            
	        foreach (DictionaryEntry entry in Students)
                lbxStudents.Items.Add(entry.Key + " " + entry.Value);
        }
    }
}

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2010-2023, FunctionX Saturday 19 November 2021 Next