The .NET HashSet Class

 Fundamentals of a Set

 Introduction
 A set is a list of items with various goals: To know whether the set is empty or it contains at least one item To find out whether a set (already) contains a certain value To compare one set to another. Some of the sought results are to find out if two sets are the same, if one set is less than the other, etc

In algebra, a set is usually represented with an uppercase letter, such as A.

 Creating a Set

To support sets, the F# language provides a module named Set. This module is included in the Microsoft.FSharp.Collections namespace.

To support sets, the .NET Framework provides a class named HashSet. This class is created in the System.Collections.Generic namespace.

 Most of the time, in algebra, to study sets, we use numbers. In all of the examples in this lesson, we will use strings to make them more interesting. Obviously, integers would be easier. If you want to use numbers, all you have to do is to replace all strings in our examples with numbers.

In F#, a set can be created from a list or an array. To allow you to create a set from a list, the Set module provides a generic function named ofList. Its signature is:

`Set.ofList : 'T list -> Set<'T>`

This function takes one argument as a list and it returns a set. Here is an example:

`let set = Set.ofList ["Kevin"; "Jane"; "Daniel"; "Ruth"; "Jane"; "Paul";]`

Notice that this set contains a certain element, namely Jane, twice.

In a .NET application, a set is a list that does not allow duplicate items.

 Most of the time, in algebra, to study sets, we use numbers. In all of the examples in this lesson, we will use strings to make them more interesting. Obviously, integers would be easier. If you want to use numbers, all you have to do is to replace all strings in our examples with numbers.
 Accessing a Set

Because a set is primarily a list, it and its members are accessed as done for a list. To access all members as one, you can use the %A operator in the desired placeholder of the printf() or the printf() function. Here is an example:

```let set = Set.ofList ["Kevin"; "Jane"; "Daniel"; "Ruth"; "Jane"; "Paul";]

printfn "Set: %A" set;```

This would produce:

`Set: set ["Daniel"; "Jane"; "Kevin"; "Paul"; "Ruth"]`

(Notice that the duplicated element was not included in the result). To access each element of the set, you can use a for...in. Here is an example:

```let set = Set.ofList ["Kevin"; "Jane"; "Daniel"; "Ruth"; "Jane"; "Paul";]

for i in set do
printfn "Name: %s" i;```

This would produce:

```Name: Daniel
Name: Jane
Name: Kevin
Name: Paul
Name: Ruth```

Other than that, the Set module contains most of the same functions as the List module, allowing you to perform all types of operations.

 Creating an Empty Set

In algebra, a set is empty if it contains no element. This is the case for a brand new set. It can also happen if the elements in the set have been deleted. In algebra, to create an empty set, use an uppercase letter and assign the phi character to it. Here is an example:

`A = ∅`

(In algebra, an empty set is also called a null set.) In algebra, to visually represent a set, we draw a circle. If the set is empty, the circle is blank:

To create an empty set, declare a variable and assign the empty property of the Set to it. Here is an example:

`let set = Set.empty;`
 Fundamental Operations on a Set

 Populating a Set

Unless a set is empty, it must have or contain something. An object included in a set is called an element or a member of the set. In algebra, to create a set, we specify an uppercase letter, followed by = { }. In the curly brackets, we list the elements separated by commas. Here is an example:

`A = { Kevin, Jane, Daniel, Ruth, Paul }`

To visually illustrate this, you can represent each element in the circle. Here is an example:

In programming, to create a set, after declaring a HashSet variable, we can call its Add() method whose syntax is:

`public bool Add(T item);`

Here are examples of calling this method:

```open System;
open System.Collections.Generic;

let names : HashSet<string> = new HashSet<string>();

for name in names do
printfn "Name: %s" name;```

This would produce:

```Name: Kevin
Name: Jane
Name: Daniel
Name: Ruth
Name: Paul```

Notice that each element in this case is a constant, or has a constant value.

Remember that one of the rules of a set is that it cannot have duplicate items. If you add an item that exists in the list already, that item would not be added. In fact, to let you know whether an item was added, the HashSet<>.Add() method returns a Boolean value:

• If the item is successfully added, the method returns true
• If the addition is denied, the method returns false and the compiler does not throw an exception
 The Number of Items in a Set

In algebra, when it comes to the number of elements in a set, there are two categories. A set is referred to as finite if it contains a constant number of items. An example is the number of students in a classroom. A set is infinite if its number of items cannot be counted. An example is the number of stars in the sky.

The HashSet class implements the ICollection<> generic interface, which gives it a property named Count. This property allows you to know the number of elements in a set. Here is an example:

```open System;
open System.Collections.Generic;

let names : HashSet<string> = new HashSet<string>();

for name in names do
printfn "Name: %s" name;

printfn "-----------------------------";

printfn "The list contains %d items" names.Count;```

This would produce:

```Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
Name: Paul Sullivan
-----------------------------
The list contains 6 items```
 Checking Whether a Set Contains a Certain Element

In algebra, to represent that a certain value "a" exists in a set A, we would write:

`a ∈ A`

This is read as "a is an element of set A" or "a is included in set A" or "Set A contains a". To support this operation, the HashSet class inherits the Contains() method from the ICollection<> interface. The method allows you to check whether the list already contains a certain item. Here are examples of calling this method:

```open System;
open System.Collections.Generic;

let names : HashSet<string> = new HashSet<string>();

for name in names do
printfn "Name: %s" name;

printfn "-----------------------------------------";

if names.Contains("Jane Owerton") then
printfn "The set contains Jane Owerton.";
else
printfn "The set doesn't contain Jane Owerton";

if names.Contains("Jane Overton") then
printfn "The set contains Jane Overton.";
else
printfn "The set doesn't contain Jane Overton";

printfn "-----------------------------------------";

printfn "The set contains %d items" names.Count;```

This would produce:

```Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
Name: Paul Sullivan
-----------------------------------------
The list doesn't contain Jane Owerton
The list contains Jane Overton.
-----------------------------------------
The list contains 6 items```

In algebra, to state that an element a is not in the set A, we write:

`a ∉ A`

This reads as "a is not an element of set A" or "a is not included in set A" or "Set A does not contain a". To perform this checking in programming, you can use the NOT Boolean operator "!".

 Creating a Duplicate Set

In algebra, after creating a set A, you may want to create another set B but that contains the same elements as A. To do this, you can simply assign the elements of A to B. This would be done as follows:

```A = { Kevin Walchild, Jane Overton, Daniel Albertson,
Ruth Oyawale, Jane Ouelette, Paul Sullivan }

B = A```

Now, sets A and B have the same elements:

To support this operation, the HashSet class provides another constructor whose syntax is:

`public HashSet(IEnumerable<T> collection);`

This constructor allows you to create a new set that is made of values from an existing set. You create the new list by passing the name of the existing list to this constructor. Here is an example:

```open System;
open System.Collections.Generic;

let names :HashSet<string> = new HashSet<string>();

let people : HashSet<string> = new HashSet<string>(names);```

Once you have created the set, you can manipulate it as you see fit. For example, you can add new items to it. Here is an example:

```open System;
open System.Collections.Generic;

let names :HashSet<string> = new HashSet<string>();

for name in names do
printfn "Name: %s" name;

printfn "The set contains %d items" names.Count;

printfn "-----------------------------";

let people : HashSet<string> = new HashSet<string>(names);

for name in people do
printfn "Name: %s" name;

printfn "The set contains %d items" people.Count;```

This would produce:

```Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
Name: Paul Sullivan
The list contains 6 items
-----------------------------
Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
Name: Paul Sullivan
Name: Antoinette Belton
Name: Joshua Melmann
The list contains 8 items```
 Operations on Sets

 Comparing Sets For Equality

Imagine you have two sets A and B defined as follows:

```A = { Kevin Walchild, Jane Overton, Daniel Albertson, Jane Ouelette }
B = { Daniel Albertson, Kevin Walchild, Jane Ouelette, Jane Overton }```

Notice that both sets have the same elements. When two sets have exact same members, we say that those sets are equal. This can be expressed as:

`A = B`

This operation is commutative, which means the above operation can also be written as:

`B = A`

We already know that all classes used in a C# application (or a .NET project) derive from the Object class and they inherit a method named Equals. This makes it possible to compare two values or two objects for equality. The HashSet class also naturally inherits this method. Although you can use that method, the HashSet class provides its own custom method named SetEquals. Its syntax is:

`public bool SetEquals(IEnumerable<T> other);`

This method takes as argument another HashSet list and compares both sets. If the sets are the same, the method returns true. Otherwise it produces a false value. Here are examples of calling this method:

```open System;
open System.Collections.Generic;

let names :HashSet<string> = new HashSet<string>();

for name in names do
printfn "Name: %s" name;

printfn "The set contains %d items" names.Count;
printfn "-----------------------------";

let people : HashSet<string> = new HashSet<string>(names);

if people.SetEquals(names) = true then
printfn "Both collections are the same.";
else
printfn "These collections are different.";

if people.SetEquals(names) = true then
printfn "Both collections are the same.";
else
printfn "These collections are different.";

for person in people do
printfn "Name: %s" person

printfn "The set contains %d items" people.Count;```

This would produce:

```Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
Name: Paul Sullivan
The list contains 6 items
-----------------------------
Both collections are the same.
These collections are different.
Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
Name: Paul Sullivan
Name: Antoinette Belton
Name: Joshua Melmann
The list contains 8 items```
 A Subset of Another Set

Imagine you have two sets A and B defined as follows:

```A = { Kevin, Jane, Daniel }
B = { Raul, Kevin, Tiffany, Daniel, Michael, Jane, Paul }```

Notice that all members of set A are also members of set B. In algebra, to express this, we write:

`A ⊂ B`

This is the same as:

` { Kevin, Jane, Daniel } ⊂ { Raul, Kevin, Tiffany, Daniel, Michael, Jane, Paul }`

We say that A is a subset of B. This can be visually illustrated as follows:

In algebra, any set is a subset of itself. Also, since the empty set doesn't have any element, the empty set is a subset of any set. We write it as:

`∅ ⊂ A`

and

`∅ ⊂ B`

An empty set is also a subset of itself.

To let you find out you whether one set is a subset of another, the HashSet class provides the IsSubsetOf() method. Its syntax is:

`public bool IsSubsetOf(IEnumerable<T> other);`

If the set passed as argument is a subset of the variable that called the method, it returns true. Otherwise, it returns false. Here is an example of calling this method:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

let people : HashSet<string> = new HashSet<string>();

if persons.IsSubsetOf(people) then
printfn "The Persons set is a subset of the People set.";
else
printfn "The Persons set is not a subset of the People set.";

for person in persons do
printfn "Name: %s" person;

printfn "The set of persons contains %d items" persons.Count;

printfn "--------------------------------------";

for person in people do
printfn "Name: %s" person;

printfn "The set of people contains %d items" people.Count;```

This would produce:

```The Persons set is a subset of the People set.
Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
The list of persons contains 3 items
--------------------------------------
Name: Raul Fitzgerald
Name: Kevin Walchild
Name: Tiffany Morales
Name: Daniel Albertson
Name: Michael Rhodia
Name: Ruth Oyawale
Name: Jane Overton
Name: Paul Sullivan
The list of people contains 8 items```

It is important to know that the subset relationship is one way; in other words, the comparison is not commutative: the fact that a set A is a subset of a set B is not vice-versa.

 A Proper Subset of Another Set

A set is a subset of itself. Also, when two sets have the exact same members, each set is a subset of the other:

On the other hand, if you have a set A that is strictly a subset of another set B, this means there is at least one element in set B that is not a member of set A. In this case, we say that set A is a property subset of set B. This can be illustrated as follows:

To let you find out if a set is a proper subset of another set, the HashSet class is equipped with the IsProperSubsetOf() method. Its syntax is:

`public bool IsProperSubsetOf(IEnumerable<T> other);`

This method takes a HashSet value as arguments and perfor10:27 AM 1/13/2015ms a comparison on their elements:

• If both sets are the same, the method returns false
• If the argument has at least one element that is not in the variable that called it, the method returns false
• If all elements of the argument's set are members of the variable that called it, the method returns true

Here are two examples of calling this method:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

let students : HashSet<string> = new HashSet<string>();

let people : HashSet<string> = new HashSet<string>();

if persons.IsProperSubsetOf(students) then
printfn "The Persons set is a proper subset of the Students set.";
else
printfn "The Persons set is not a proper subset of the Students set.";

if persons.IsProperSubsetOf(people) then
printfn "The Persons set is a proper subset of the People set.";
else
printfn "The Persons set is not a proper subset of the People set.";```

This would produce:

```The Persons set is not a proper subset of the Students set.
The Persons set is a proper subset of the People set.```
 A Super-Set of an Existing Set

Remember that a sub-set is a set whose all elements are also found in another set. A super-set is the reverse of a sub-set. That is, in a superset, all the elements of a set B are found in a set A but set A may have elements that are not found in set B. In algebra, this can be written as follows:

`B ⊃ A`

To help you make this comparison, the HashSet class is equipped with a method named IsSupersetOf. Its syntax is:

`public bool IsSupersetOf(IEnumerable<T> other);`

This method takes a HashSet object as argument and compares its elements to those of the variable that called it. If all the elements of the argument are found in the variable that called it, the method returns true.

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

let students : HashSet<string> = new HashSet<string>();

let people : HashSet<string> = new HashSet<string>();

if persons.SetEquals(students) then
printfn "Set Persons is equal to set Students.";
else
printfn "Set Persons is different from set Students.";

if persons.IsSubsetOf(people) then
printfn "Set Persons is a sub-set of People.";
else
printfn "Set Persons is not a sub-set of People.";

if people.IsSupersetOf(persons) then
printfn "Set People is a super-set of Persons.";
else
printfn "Set People is not a super-set of Set Persons.";

if persons.IsProperSubsetOf(students) then
printfn "The Persons set is a proper subset of the Students set.";
else
printfn "The Persons set is not a proper subset of the Students set.";

if persons.IsProperSubsetOf(people) then
printfn "The Persons set is a proper subset of the People set.";
else
printfn "The Persons set is not a proper subset of the People set.";```

This would produce:

```Set Persons is equal to set Students.
Set Persons is a sub-set of People.
Set People is a super-set of Persons.
The Persons set is not a proper subset of the Students set.
The Persons set is a proper subset of the People set.```

 A Proper Super-Set of an Existing Set

When it comes to a super-set, if two sets are the same, each one is considered a super-set of the other and the IsSupersetOf() method returns true. By contrast, if a set B is a super-set of A but both sets are not the same, that is, set B has more elements than set A, set B is said to be a property super-set of A. To let you make the comparison to determine this, the HashSet class is equipped with a method named IsProperSupersetOf. Its syntax is:

`public bool IsProperSupersetOf(IEnumerable<T> other);`

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

let students : HashSet<string> = new HashSet<string>();

let people : HashSet<string> = new HashSet<string>();

if persons.SetEquals(students) then
printfn "Set Persons is equal to set Students.";
else
printfn "Set Persons is different from set Students.";

if persons.IsSubsetOf(people) then
printfn "Set Persons is a sub-set of People.";
else
printfn "Set Persons is not a sub-set of People.";

if people.IsSupersetOf(persons) then
printfn "Set People is a super-set of Persons.";
else
printfn "Set People is not a super-set of Set Persons.";

if persons.IsProperSubsetOf(students) then
printfn "The Persons set is a proper subset of the Students set.";
else
printfn "The Persons set is not a proper subset of the Students set.";

if persons.IsProperSubsetOf(people) then
printfn "The Persons set is a proper subset of the People set.";
else
printfn "The Persons set is not a proper subset of the People set.";

if people.IsProperSupersetOf(persons) then
printfn "Set People is a proper super-set of set Persons.";
else
printfn "Set People is not a proper super set of set Persons.";```

This would produce:

```Set Persons is equal to set Students.
Set Persons is a sub-set of People.
Set People is a super-set of Persons.
The Persons set is not a proper subset of the Students set.
The Persons set is a proper subset of the People set.
Set People is a proper super-set of set Persons.```
 A Union of Two Sets

Imagine you have two sets A and B defined as follows:

```A = { Kevin, Jane, Daniel }
B = { Raul, Kevin, Tiffany, Michael, Jane }```

One of the operations you can perform on them is to create a set that contains a list of all their elements. That is, you would get a list that contains elements that are present in each set. If there is an element present in both sets, it would be included only once.

A union of two sets is the list of all elements that belong to both sets. Remember that there is no reason to include an element twice if it already belongs to one of the sets. In algebra, this operation is written as follows:

`A ∪ B = { x|x ∈ A or x ∈ B }`

This can be visually illustrated as follows:

To help you unite two sets, the HashSet class is equipped with a method named UnionWith. Its syntax is:

`public void UnionWith(IEnumerable<T> other);`

This method takes as argument the set whose elements would be combined to those of the set that called the method. Here is an example of calling this method:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for person in persons do
printfn "Name: %s" person;

printfn "The set of persons contains %d items" persons.Count;
printfn "------------------------------------";

let people : HashSet<string> = new HashSet<string>();

for person in people do
printfn "%s" person;

printfn "The set of people contains %d items" people.Count;

printfn "------------------------------------";

persons.UnionWith(people);

for str in persons do
printfn "%s" str;

printfn "Set Person contains %d items" persons.Count;
printfn "------------------------------------";```

This would produce:

```Name: Kevin Walchild
Name: Jane Overton
Name: Daniel Albertson
Name: Ruth Oyawale
Name: Jane Ouelette
The list of Persons contains 5 items
------------------------------------
Antoinette Belton
Joshua Melmann
Paul Sullivan
The list of People contains 3 items
------------------------------------
Kevin Walchild
Jane Overton
Daniel Albertson
Ruth Oyawale
Jane Ouelette
Antoinette Belton
Joshua Melmann
Paul Sullivan
The list of Person contains 8 items
------------------------------------```

It is important to know that this method performs a comparison on the elements of both sets so that the result would not allow any duplicate item.

 A Universal Set

If you have two or more sets, a universal set is a list that contains all elements of those sets. For example, if you have three sets A, B, and C, you can write their universal set as:

`A ∪ B ∪ C`

To programmatically create a universal set, simply call the HashSet<>.UnionWith() method as necessary.

 An Intersection of Sets

The intersection between two sets is the list of only members that belong to both sets. That is, the elements that belong to one set but do not belong to the other set are excluded. In algebra, we write it as follows:

`A ∩ B = { x|x ∈ A and x ∈ B }`

This can be visually illustrated as follows:

To help you reduce a set to its intersecting elements with regards to another set, the HashSet class provides the IntersectWith() method. Its syntax is:

`public void IntersectWith(IEnumerable<T> other);`

This takes a HashSet object as argument. It finds the elements from the argument that are also present in the variable that called it and it removes the elements that are found in the variable that called it but are not found in the argument.

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;

printfn "-----------------------------------------";

let people : HashSet<string> = new HashSet<string>();

for person in people do
printfn "Name: %s" person;

printfn "Set People contains %d names" people.Count;

printfn "-----------------------------------------";

persons.IntersectWith(people);

printfn "The names in sets People and Persons are:";

for person in persons do
printfn "%s" person;

printfn "Set Persons NOW contains %d names" persons.Count;
printfn "-----------------------------------------";```

This would produce:

```Joshua Akron
Tiffany Morales
Michael Herance
Frank Maguire
Paul Sullivan
James Matheath
Jane Overton
Jonathan Beshan
Set Persons contains 8 names
-----------------------------------------
Name: Raul Fitzgerald
Name: Kevin Walchild
Name: Tiffany Morales
Name: Daniel Albertson
Name: Michael Rhodia
Name: Frank Maguire
Name: Ruth Oyawale
Name: Jane Overton
Name: Paul Sullivan
Name: Bethany Syon
Set People contains 10 names
-----------------------------------------
The names in sets People and Persons are:
Tiffany Morales
Frank Maguire
Paul Sullivan
Jane Overton
Set Persons contains 4 names
-----------------------------------------```
 Overlapped Sets

As seen above, the intersecting set is a list of elements shared by two sets. The comparison consists of finding out whether two lists intersect; that is, whether they have at least one common member. To perform this comparison, you can call the Overlaps() method of the HashSet class. Its syntax is:

`public bool Overlaps(IEnumerable<T> other);`

This method too takes a HashSet object as argument and compares it to the object that called it. If it finds at least one value that exists in both lists, it returns true. If there is no single value that both lists share, the method returns false. Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for str in persons do
printfn "%s" str;

printfn "Set Persons contains %d names." persons.Count;

printfn "---------------------------------------------------------------";

let people : HashSet<string> = new HashSet<string>();

if people.Overlaps(persons) = true then
printfn "The Persons and the People lists have at least one name in common.";
else
printfn "The Persons and the People lists have no name in common.";

printfn "---------------------------------------------------------------";

for str in people do
printfn "%s" str;

printfn "Set People contains %d names." people.Count;

printfn "---------------------------------------------------------------";

let students : HashSet<string> = new HashSet<string>();

if students.Overlaps(persons) then
printfn "The Persons and the Students lists have at least one name in common.";
else
printfn "The Persons and the Students lists have no name in common.";

printfn "---------------------------------------------------------------";```

This would produce:

```Kevin Walchild
Jane Overton
Daniel Albertson
Ruth Oyawale
Jane Ouelette
Paul Sullivan
Set Persons contains 6 names.
---------------------------------------------------------------
The Persons and the People lists have no name in common.
---------------------------------------------------------------
Antoinette Belton
Joshua Melmann
Deborah Callum
Set People contains 3 names.
---------------------------------------------------------------
The Persons and the Students lists have at least one name in common.
---------------------------------------------------------------```
 Set Difference

Consider two sets A and B. The difference between a set A from a set B is the list of elements that are found in set A but are not found in set B. In algebra, this is written as follows:

`A - B = { x|x ∈ A and x ∉ B }`

This can be illustrated as follows:

To let you perform this operation, the HashSet class provides a method named ExceptWith. Its syntax is:

`public void ExceptWith(IEnumerable<T> other);`

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;

printfn "---------------------------------------------------------------";

let people : HashSet<string> = new HashSet<string>();

for person in people do
printfn "Name: %s" person;

printfn "Set People contains %d names" people.Count;

printfn "---------------------------------------------------------------";

persons.ExceptWith(people);

printfn "The names found in set People but not in set Persons are:";

for person in persons do
printfn "%s" person;

printfn "Set Persons NOW contains %d names" persons.Count;
printfn "---------------------------------------------------------------";```

This would produce:

```Joshua Akron
Tiffany Morales
Michael Herance
Frank Maguire
Paul Sullivan
James Matheath
Jane Overton
Jonathan Beshan
Set Persons contains 8 names
---------------------------------------------------------------
Name: Raul Fitzgerald
Name: Kevin Walchild
Name: Tiffany Morales
Name: Daniel Albertson
Name: Michael Rhodia
Name: Frank Maguire
Name: Ruth Oyawale
Name: Jane Overton
Name: Paul Sullivan
Name: Bethany Syon
Set People contains 10 names
---------------------------------------------------------------
The names in sets People and Persons are:
Joshua Akron
Michael Herance
James Matheath
Jonathan Beshan
Set Persons NOW contains 4 names
---------------------------------------------------------------```
 Symmetric Difference

Consider two sets A and B. The symmetric difference between those sets is the list of elements that belong to each set but do not belong to their intersection. This can be illustrated as follows:

As you can guess, this is the reverse of the intersection. That is, it is the union of the sets excluding their intersection. To let you perform this operation, the HashSet class is equipped with the SymmetricExceptWith() method. Its syntax is:

`public void SymmetricExceptWith(IEnumerable<T> other);`

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;

printfn "---------------------------------------------------------------";

let people : HashSet<string> = new HashSet<string>();

for person in people do
printfn "Name: %s" person;

printfn "Set People contains %d names" people.Count;

printfn "---------------------------------------------------------------";

persons.SymmetricExceptWith(people);

printfn "The names found in each set People and Persons but not common to both are:";

for person in persons do
printfn "%s" person;

printfn "Set Persons NOW contains %d names" persons.Count;
printfn "---------------------------------------------------------------";```

This would produce:

```Joshua Akron
Tiffany Morales
Michael Herance
Frank Maguire
Paul Sullivan
James Matheath
Jane Overton
Jonathan Beshan
Set Persons contains 8 names
---------------------------------------------------------------
Name: Raul Fitzgerald
Name: Kevin Walchild
Name: Tiffany Morales
Name: Daniel Albertson
Name: Michael Rhodia
Name: Frank Maguire
Name: Ruth Oyawale
Name: Jane Overton
Name: Paul Sullivan
Name: Bethany Syon
Set People contains 10 names
---------------------------------------------------------------
The names found in each set People and Persons but not common to both are:
Joshua Akron
Daniel Albertson
Michael Herance
Ruth Oyawale
Bethany Syon
James Matheath
Jonathan Beshan
Raul Fitzgerald
Kevin Walchild
Michael Rhodia
Set Persons NOW contains 10 names
---------------------------------------------------------------```
 Deleting Items From a Set

 Deleting an Item

The HashSet class implements the ICollection<> interface. As such, it inherits the Remove() method that allows you to delete an item from the list. In some cases, you may want to delete an element based on a specific condition. To support this operation, the HashSet class provides the RemoveWhere() method. Its syntax is:

`public int RemoveWhere(Predicate<T> match);`

This method takes as argument a delegate that specifies what condition would be applied to any element that must be removed.

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;

printfn "---------------------------------------------------------------";

persons.RemoveWhere(fun person -> person.StartsWith("J"));

printfn "After removing all names that start with J, the set of Persons now is:";

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;
printfn "---------------------------------------------------------------";```

This would produce:

```Joshua Akron
James Matheath
Tiffany Morales
Jane Overton
Michael Herance
Frank Maguire
Paul Sullivan
Jonathan Beshan
Set Persons contains 8 names
---------------------------------------------------------------
After removing all names that start with J, the set of Persons now is:
Tiffany Morales
Michael Herance
Frank Maguire
Paul Sullivan
Set Persons contains 4 names
---------------------------------------------------------------```
 Clearing a Set

As an implemented of the ICollection interface, the HashSet class inherits the Clear() method that can be used remove all items from a set.

Here is an example:

```open System;
open System.Collections.Generic;

let persons : HashSet<string>  = new HashSet<string>();

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;

printfn "---------------------------------------------------------------";

persons.Clear();

printfn "After removing all names names from the Persons set, it now contains:";

for person in persons do
printfn "%s" person;

printfn "Set Persons contains %d names" persons.Count;
printfn "---------------------------------------------------------------";```

This would produce:

```Joshua Akron
James Matheath
Tiffany Morales
Jane Overton
Michael Herance
Frank Maguire
Paul Sullivan
Jonathan Beshan
Set Persons contains 8 names
---------------------------------------------------------------
After removing all names names from the Persons set, it now contanis:
Set Persons contains 0 names
---------------------------------------------------------------```