In Swift there are three primary collection types – arrays, dictionaries and sets. We’ve already covered arrays and dictionaries in previous posts and in this post we’re going to complete the set (no pun intended) by looking at sets.

## What is a Set?

In Swift, sets are unordered collections of unique values. This means that like a dictionary, the values held in a Swift set aren’t held in any particular order and like the keys in a dictionary, there can’t be any duplicate values.

Like the other collection types in Swift, sets in Swift are also strongly typed. This means that only values of one specified type can be held within a set and although this may seem restrictive, as we’ve seen in previous articles, this actually helps us to avoid bugs by ensuring that we don’t insert values of the incorrect type.

## Hash Values for Set Types

On top of only being able to hold a single type, the Swift language, also imposes one more requirement on the types of values that can be held in a set – the types of values that can be held *must* conform to Swift’s *hashable* protocol.

This may sound all fancy but all this really means is that values of the specified type must have an `Int`

property called `hashValue`

that can be used as a representation of the value.

In addition, because the `Hashable`

protocol in Swift itself conforms to the `Equatable`

protocol, it means that the type must also supply an implementation of the equality operator (`==`

) as well. The Swift language then uses the `hashValue`

and the equality operator to compare different values within the set (via their `hashValue`

) to ensure that they are unique.

So you may be wondering which types of values conform to this `Hashable`

protocol. The good news here is that pretty much all of the basic types in Swift are *hashable* by default. This includes the `String`

, `Int`

, `Double`

and `Bool`

types as well as any enumeration types that don’t have associated values.

Ok, so that’s *what* a set is (a strongly typed, unordered collection of unique values) but what about actually creating one? Before we look at how to do this, let’s first look at how the *mutability* of sets is controlled.

## Declaring and Initialising a Set

### Mutable versus Immutable Sets

As with other collection types in Swift, the mutability of a set is governed by whether we declare that set using the `var`

or `let`

keywords.

As we’ve seen with other collections, if declared with the `var`

keyword, the contents of the set will be *mutable* – meaning that it can be *mutated* or *changed* by adding, removing or changing items within the set.

If the set is declared with the `let`

keyword however the set is said to be *immutable* or *unchangeable*. This means that both the sets size and its contents cannot be changed.

### Creating an Empty Set

In Swift, there are a number of ways that you can create a set. The first of these is using initialiser syntax.

Initialisation syntax makes use of an initialisation function:

1 | var firstSet = Set<String>() |

Let’s walk through this slowly to start with.

Here I’ve started off our declaration as we would when defining any variable – using the `var`

keyword. As we’ve just seen, this means that the set I’m creating here is going to be *mutable* (i.e. we’re going to be able to modify it). We then have the name of the variable into which we’re going to store the set.

In this example I’m also taking advantage of Swift’s type inference mechanism as well. This allows me to infer the type of our `firstSet`

variable, without having to explicitly state it. We’ll come to exactly what *type* this set is in a moment.

After declaring our mutable set variable we then have the assignment operator and then the `Set`

type name. The `Set`

type (in similar fashion to the `Array`

type we saw in previous posts) is a *generic* type in Swift. This means that when we declare a set using initialiser syntax we not only supply the `Set`

type but also have to supply an additional type between angled brackets (`< >`

) to define the type of values that the set will hold. In this case I’ve declared the set to hold values of type `String`

so the full type for the set is `Set<String>`

and Swift infers it as such.

The final piece to the puzzle comes after the sets type. These are a set of parentheses that represent the call to the initialisation function which creates the set. The `Set`

type in Swift has a number of these initialisation functions, some with parameters and one without, and it is this form, the one without an argument, that creates an empty set of the specified type.

### Creating an Empty Set with an Array Literal

So that’s how to create an empty set using initialisation syntax but we actually have a couple of other ways of creating empty sets in Swift as well, both of which use array literals.

As I mentioned, the `Set`

type in Swift has a number of initialisation functions and one of these functions takes an array literal as a parameter. This particular initialisation function then uses that array parameter to populate the contents of the set it creates.

Our first alternative for creating an empty set then, is to make use of this initialisation function and provide it with an *empty* array literal:

1 | let secondSet = Set<Double>([]) |

The syntax is almost exactly the same as we’ve just seen and the result is essentially the same. This time I’ve declared `secondSet`

using the `let`

keyword resulting in an *immutable* set (one where we won’t be able to change the contents of the set) and have declared the set to hold values of type `Double`

instead of `String`

.

I’ve also supplied the empty array literal (`[]`

) as a parameter to the initialisation function. The effect is that it uses this *empty* array literal to create an *empty* set of type `Set<Double>`

.

Our final way of creating an an empty set in Swift is similar to this last one, but instead uses assignment.

In Swift, we can actually split the declaration of our set from it’s initialisation and as long as the sets type can be inferred from the context (which in the following example it can because of the explicit type declaration), we can *assign* an empty array literal to perform initialisation.

The result is exactly the same as our previous example:

1 2 | let thirdSet : Set<Double> thirdSet = [] |

Now, empty sets are all very well but they’re not *that* interesting. What about creating a set that actually contains something useful?

## Creating Sets That Actually Contain Some Values

In Swift, there are a couple of ways to declare and initialise a set that contains some values and the first technique is a simple extension to what we’ve already seen.

### Creating a Set with an Array Literal

We’ve already seen how an empty set can be created by supplying an *empty* array literal as an initialisation parameter, but (as you can probably guess) we can also create a set that contains an initial set of values by using an array literal that itself contains some values.

Both the initialisation syntax (calling an initialisation function on the `Set`

type) or the assignment approach we just looked at both work:

1 2 3 4 | let fourthSet = Set<Int>([10, 30]) // Intialisation Syntax let fifthSet : Set<Double> fifthSet = [10.1, 37.2, 33.5] // Assignment |

In this example, we create two new *immutable* `Set`

s. The first, (`fourthSet`

) contains values of type `Int`

and is inferred to be of type `Set<Int>`

. The second, (`fifthSet`

) is declared to store values of type `Double`

and is inferred to be of type `Set<Double>`

. In both cases, we also initialise the sets with values of the relevant types.

Now, you might think we’re done on the initialisation front, but there is one more, lesser known, initialisation option that I wanted to look at before we move on and that is initialising a set using a *sequence*.

### Creating a Set with a Sequence

We’ve already touched on sequences in previous posts and took a cursory look at them when we talked about the open and closed range operators. The final initialisation function at our disposal makes use of sequences as it takes a sequence as a parameter and then uses the sequence to populate the elements within the set (one element in the set for each element in the sequence):

1 | let sixthSet = Set<Int>(1...5) |

The result of the example above is an immutable set that stores values of type `Int`

and contains the values `1`

, `2`

, `3`

, `4`

and `5`

.

So we now know how to creating both an empty set and a set that actually contains some values. But what about working how many elements are already *in* a set? Let’s look at that next.

### Checking if a Set is Empty

There are two ways in Swift that we can use to check how many elements are in set, both of which are accessible as properties of a given set.

This first of these properties is the `isEmpty`

property. As the name suggests, it can be used to test whether the set is empty and returns a `Bool`

value to indicate whether the set is empty or not:

1 2 | firstSet.isEmpty // true |

### Counting the Number of Elements in a Set

In addition to being able to test whether a set is empty or not, we can also determine the exact number of elements that are in a set.

Again, this is done via a property of the `Set`

type. This time the property is called `count`

and returns an `Int`

value representing the number of elements contained in the set:

1 2 3 4 | firstSet.count // 0 fifthSet.count // 3 |

## Adding an Element to a Set

Now that we know how to create a set that contains some values and count the number of elements in a set, the next thing to look at is how to add *new* elements to a set. For sets, this is done using the `insert(_:)`

function.

The `insert(_:)`

function accepts a single parameter of the same type as the elements stored within the set. (You’ll get an error if you try to supply a value of an incompatible type).

Let’s have look at an example.

Note: For this example and later ones I’ll use in this post I’m going to revisit an example I’ve used in a previous post, one using the characters from the latest Star Wars films.

Initially we’re going to create an empty `forceAwakens`

set to hold some of the characters from the movie The Force Awakens, and we’re initially going to add a single element to it:

1 2 3 4 5 | var forceAwakens = Set<String>() forceAwakens.count // 0 forceAwakens.isEmpty // true forceAwakens.insert("Rey") // 'forceAwakens' now contains one item "Rey" forceAwakens.count // 1 |

In this example, we declare a new set called `forceAwakens`

. We’ll use this to hold the names of the characters in the film.

Initially, the set is empty (and therefore has a `count`

of `0`

) but we then use the `insert(_:)`

function to insert the first of our characters (`Rey`

). The result is that the set contains one element and the `count`

reflects this.

To add multiple elements to a set, all we do is use the `insert(_:)`

function multiple times within a loop:

1 2 3 4 5 | for character in ["Finn", "BB-8", "Yoda", "C-3PO", "Han Solo", "Princes Leia"] { forceAwakens.insert(character) } // {"Rey", "Han Solo", "Princess Leia", "BB-8", "Yoda", "C-3PO", "Chewbacca", "Finn"} // Note: The elements in your set may be in a different order. |

As we’ll see later, there is also another way to add elements to a set using set operations (the `unionInPlace(_:)`

function to be precise). Before we look at this though, we’ve got a couple of other things to look at. The first of these is how to *access* elements within a set.

## Finding Elements in a Set

Let’s start this section off gently. We’ve now created our `forceAwakens`

set, and have learnt how to create it with some initial characters and also how to add additional characters to it, but what about checking on whether a value is already in the set?

### Finding If an Element is in a Set

To find out whether an item is already in a set or not, we can use the `contains(_:)`

function.

The `contains(_:)`

function takes a single element of the same type as the elements held within the set and returns a boolean value to indicate whether the element is present or not:

1 2 | forceAwakens.contains("Yoda") // true |

But we can go beyond simply checking whether an element is already in a set or not. We can also get the *index* of that element.

### Finding the Index of an Element in a Set

As I mentioned at the start of this article, the elements in a set are not held in a defined order, but once inserted, elements in the set *are* located at particular indexes. As with other collections, the indexes of elements in a set start at `0`

and then increment up to one less than the number of elements in the set.

For example, what if we wanted to get hold of the index of `Yoda`

within the set. We could write:

1 | forceAwakens.indexOf("Yoda") |

Note: If you run this yourself, you will likely get a different answer due to the unordered nature of the `Set`

type.

The `indexOf(_:)`

function returns a value of type `SetIndex<T>`

where `T`

is the type of value held in the set. We’ll see this again later in this article.

## Iterating Over a Set

In addition to being able to identify the index of an element in a set we can also *iterate* over the sets elements.

We’ve seen this in previous articles with some of the other Swift collection types. The only thing to watch out for here is that the elements in the set are not held in any particular order so there is no guarantee about the order in which they will appear:

1 2 3 4 | for character in forceAwakens { print(character) } // Rey, Han Solo, Princess Leia, BB-8, Yoda, C-3PO, Chewbacca, Finn |

Note: If you *do* want the elements in a set in a given order, you can also use the `sort()`

function to sort the values in the set before iterating over the array that results:

1 2 3 4 | for character in forceAwakens.sort() { print(character) } // BB-8, C-3PO, Chewbacca, Finn, Han Solo, Princess Leia, Rey, Yoda |

Now that we know how to access elements in a set, there’s one final mechanism that I wanted to look at. I’ve left this one until last because not only does it access the element in the set, but it also modifies the set itself. This is the `popFirst()`

function.

## Removing Elements from a Set

### Removing the First Element in a Set

If you’ve done any sort of programming before, you might be used to the idea of *pushing* things onto a stack and *popping* them off. I always think of it as a pile of plates. You push a plate onto the top of the stack and pop it back off.

The `popFirst()`

function embodies this idea and is used to *pop*, the (notionally) first element of the set, returning the element and removing it from the set in the process:

1 2 3 4 5 | // forceAwakens contains: {"Rey", "Han Solo", "Princess Leia", "BB-8", "Yoda", "C-3PO", "Chewbacca", "Finn"} let firstVal = forceAwakens.popFirst() print(firstVal) // Rey // forceAwakens now contains: {"Han Solo", "Princess Leia", "BB-8", "Yoda", "C-3PO", "Chewbacca", "Finn"} |

The `popFirst()`

function actually returns an optional type. This accounts for the fact that in a situation where the set is empty, there is no value to return. In this situation, the `popFirst()`

returns `nil`

.

Now, we’re not done with removing the first element from a set. In addition to the `popFirst()`

function, the `Set`

type also has a `removeFirst()`

function.

The `removeFirst()`

function, has exactly the same behaviour as the the `popFirst()`

function – it returns the (notionally) first element in the set and in doing so, removes that element from the set itself. However, unlike the `popFirst()`

function, the `removeFirst()`

function can only be used with a set that contains at least one element. If the set is empty and the `removeFirst()`

function is called, an error will be thrown. It’s therefore prudent to first check that the set has at least one element *before* calling the `removeFirst()`

function:

1 2 3 4 5 6 7 | // forceAwakens contains: {"Han Solo", "Princess Leia", "BB-8", "Yoda", "C-3PO", "Chewbacca", "Finn"} if forceAwakens.count > 0 { let nextVal = forceAwakens.removeFirst() print(nextVal) } // Han Solo // forceAwakens now contains: {"Princess Leia", "BB-8", "Yoda", "C-3PO", "Chewbacca", "Finn"} |

So between the `popFirst()`

and `removeFirst()`

functions, we now know how to remove the first element from a set. But what if the element we wanted to remove wasn’t the first element? This is where the `remove(_:)`

and `removeAtIndex(_:)`

functions come in. Let’s look at the `remove(_:)`

function first.

### Removing an Element from a Set

The `remove(_:)`

function allows us to remove a single element from the set on which the function is called. The function takes a single parameter of the same type as the elements stored within the set which is used to indicate the element you wish to removed. For example, say we wanted to remove `Yoda`

from our `forceAwakens`

set we could write:

1 2 3 4 5 | // forceAwakens contains: {"Princess Leia", "BB-8", "Yoda", "C-3PO", "Chewbacca", "Finn"} let item = forceAwakens.remove("Yoda") print(item) // Yoda // forceAwakens now contains: {"Princess Leia", "BB-8", "C-3PO", "Chewbacca", "Finn"} |

As with the `popFirst()`

and `removeFirst()`

functions, the `remove(_:)`

function returns the element that was removed from the set or `nil`

if the element was not present (the return type of the `remove(_:)`

function is an optional to account for this).

### Removing An Element from a Set By Index

In addition to being able to remove an element directly, we can also remove an element from a set using the index of that element.

We saw how to get the index of an element earlier using the `indexOf(_:)`

function. That returns an optional value representing the index of the specified element. Once we have the index, we can then supply that index to the `removeAtIndex(_:)`

method which will both return the element at the given index *and* remove it from the set.

The thing to remember with the `removeAtIndex(_:)`

function is that because the element must already be in the set (in order to have a valid index), the function returns a non-optional (rather than optional) value of the same type as those stored within the set:

1 2 3 4 5 6 7 | // forceAwakens contains: {"Princess Leia", "BB-8", "C-3PO", "Chewbacca", "Finn"} if let idx = forceAwakens.indexOf("BB-8") { var otherItem = forceAwakens.removeAtIndex(idx) print(otherItem) } // BB-8 // forceAwakens now contains: {"Princess Leia", "C-3PO", "Chewbacca", "Finn"} |

### Removing Multiple Items from a Set

By now, we know how to retrieve elements from a set, and also how to remove individual elements (whether they be the nominally first element of the set or elsewhere). But what if we wanted to remove multiple items from a set?

There are a number of ways to approach this, two of which we’ll touch on now, and a couple that we’ll look at later in the article when we look at *set operations*. For now, let’s start with the simplistic approaches.

Given what we’ve learnt just now, the easiest way to remove multiple items from a set is to call one of the functions we just looked at multiple times. For example, we could call the `remove(_:)`

function multiple times to remove a number of elements form the set:

1 2 3 4 5 6 7 8 | // forceAwakens contains: {"Princess Leia", "C-3PO", "Chewbacca", "Finn"} for character in ["Finn", "C-3PO"] { let character = forceAwakens.remove(character) print(character) } // Finn // C-3PO // forceAwakens now contains: {"Princess Leia", "Chewbacca"} |

There is however an alternative if we want to remove *all* elements from a set. Built into the `Set`

type, is the `removeAll(keepCapacity:)`

function which as you might expect, removes *all* the elements from a set. Note: The function has a default parameter for the `keepCapacity`

parameter which most of the time you can ignore unless you explicitly want to keep the capacity of the set for performance reasons:

1 2 | forceAwakens.removeAll() // forceAwakens now contains: [] |

Ok, so far we’ve covered the basics of Swift sets and if you stop reading here, you’d be wondering why you would want to use them. After all, they sound pretty similar to arrays (except for the non-ordered bit) and they don’t seem to be giving you much more benefit – so why us them?

The reality is that sets in Swift are actually extremely powerful but their real power comes from their ability to perform *set operations* and check for *set membership and set equality*. It’s these aspect that I want to touch on next. Let’s start by looking at the concepts of set membership and set equality.

## Set Membership and Equality

You might remember some set theory from school but before we dive in, let’s have a bit of a refresher. In the diagram below, we have three sets – A, B and C. These are going to represent three sets of Star Wars characters:

The first set, set A, is going to be our set of characters from the film The Return of the Jedi. This set is declared to contain the following characters:

1 | var returnOfTheJedi = Set<String>(["Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"]) |

The next set, set B, is our set of characters from the newly released movie The Force Awakens. This set is declared as follows:

1 | var forceAwakens2 = Set<String>(["Finn", "BB-8", "Yoda", "Chewbacca", "C-3PO", "R2-D2"]) |

The characters in this set have some overlap with the characters in The Return of the Jedi, namely characters like `Yoda`

, `Chewbacca`

, `C-3PO`

and `R2-D2`

.

The overlap of sets A and B represent the characters that are in both set A (The Return of the Jedi) *and* set B (The Force Awakens). These include `Yoda`

, `Chewbacca`

, `C-3PO`

and `R2-D2`

.

Our final set is set C. Set C contains a single element and represents the robots from the film The Force Awakens (`BB-8`

). Set C is declared as follows:

1 | var robots = Set<String>(["BB-8"]) |

Set C is said to be a *subset* of set B because all of the elements in Set B are are *contained* within Set C.

By inference, set B is also said to be a *superset* of set C because it *contains* all the elements of set C.

Ok, that lays out the various sets we’re going to use in the following examples. Let’s start off easy by examining the set statements I made above, but this time using Swift code.

Let’s start off by looking at how to determine whether the elements in two sets are equal.

### Set Equality

Testing whether two sets are equal is actually really easy in Swift. All we have to do is to use the ‘is equal’ operator (`==`

) just as you would with any boolean comparison.

For example, let’s first declare another set that contains identical elements to the `robots`

set we saw just now:

1 | var robots2 = Set<String>(["BB-8"]) |

In the case of sets, the ‘is equal’ operator will only return `true`

if the two sets contain exactly the same elements. If either set contains additional elements, the ‘is equal’ operator will return false:

1 2 3 4 5 | robots2 == robots // true robots == forceAwakens2 // false |

Note that in this second case, despite the fact that all of the elements in the `robots`

set are contained within the `forceAwakens2`

set, the comparison returns `false`

because the sets do not contain exactly the same elements.

### Subset

The next thing we may want to test for is whether one set is a *subset* of another set. As we saw from our diagram, the robots from the Force Awakens (set C) is a subset of the characters in the film the Force Awakens (set B).

We can actually test for this in Swift using the `isSubsetOf(_:)`

function. The function takes another set (or sequence) as it’s single parameter and returns a boolean value indicating whether all the elements of the first set are contained within the set supplied as a parameter:

1 2 3 4 5 | robots.isSubsetOf(forceAwakens2) // true robots2.isSubsetOf(robots) // true |

Notice that in the case of the second set, the function also returns a value of `true`

. This is due to the fact that these sets contain identical elements and the test (whether all elements of the first set are contained within the second set) actually returns `true`

.

### Strict Subset

Now, in addition to the `isSubsetOf(_:)`

function, sets in Swift also have an additional function, the `isStrictSubsetOf(_:)`

function. This function behaves in exactly the same way as the `isSubsetOf(_:)`

function but returns `false`

if the two sets are equal. For example:

1 2 3 4 5 | robots.isStrictSubsetOf(forceAwakens2) // true robots2.isStrictSubsetOf(robots) // false |

Notice this time that the comparison of the `robots2`

set to the `robots`

set, returns `false`

. This is because the sets are equal actually equal.

Ok, that’s subsets, but let’s flip this around and look at it from the other perspective, whether one set is a *superset* of another or not.

### Superset

As you might have guessed, sets in Swift also have a function called `isSupersetOf(_:)`

. This function allows us to test whether one is a superset of another. Again this function returns a boolean value:

1 2 | forceAwakens2.isSupersetOf(robots) // true |

And in similar fashion to the `isSubset(_:)`

function we just looked at, the `isSupersetOf(_:)`

function also returns `true`

for two sets if they have equal elements (as all the elements of the second set are contained within the first):

1 2 | robots2.isSupersetOf(robots) // true |

### Strict Superset

Finally, we also have the `isStrictSupersetOf(_:)`

function. As you might expect, this behaves in the same manner as the `isSupersetOf(_:)`

function but returns `false`

if the two sets are identical:

1 2 3 4 5 | forceAwakens2.isStrictSupersetOf(robots) // true robots2.isStrictSupersetOf(robots) // false |

That about wraps up the set membership functions for Swift sets, but there is one final function that we need to look at before we move on. That is the `isDisjointWith(_:)`

function.

### Disjoint

So far we’ve looked at whether one set is a *superset* or *subset* of another set, but the `isDisjointWith(_:)`

function allows us to test whether there is *no* overlap between two sets (or in fact, no overlap between a given set and any other value that compiles with Swift’s `sequenceType`

protocol such as another set or an array).

For example, in our three Star Wars sets, there is no overlap between the characters in the Return of the Jedi movie (set A) and the robots in the movie the Force Awakens (set C). We can test for this as follows:

1 2 | returnOfTheJedi.isDisjointWith(robots) // true |

But there *is* an overlap between the `forceAwakens2`

set and the `robots`

set and the `isDisjoint(_:)`

function therefore returns `false`

as the two sets overlap:

1 2 | forceAwakens2.isDisjointWith(robots) // false |

## Set Functions

Ok, so we’ve covered the basics of sets and can now test whether sets are either supersets or subsets of each other and whether there is no overlap between the two sets. If we follow this course of thinking, the next logical thing to look at is how to test whether there is a *partial* overlap between two sets. Let’s do that next.

### Intersect / Intersect In Place

If we go back to the diagram of our three Star Wars sets, we can see that there is a partial overlap between the `returnOfTheJedi`

set and the `forceAwakens2`

set:

In isolation, the set can be visualised as follows:

The `Set`

type in Swift, has two functions that allow us to test for this overlap. The first is the `intersect(_:)`

function.

The `intersect(_:)`

function takes a single parameter. The parameter is anything that compiles with Swift’s `SequenceType`

protocol and generates elements of the same type as those stored within the `Set`

. In reality this usually means another `Set`

or `Array`

but it’s obviously not restricted to these types.

When called, the `intersect(_:)`

function returns a `Set`

containing those elements that are members of *both* the set on which the function is called *and* the set that is supplied as a parameter. For example:

1 2 3 4 | // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} // forceAwakens2 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} let commonCharacters = returnOfTheJedi.intersect(forceAwakens2) // commonCharacters contains {"Yoda", "Chewbacca", "C-3PO", "R2-D2"} |

But as I mentioned, we don’t *have* to supply another set as a parameter, we *could* supply an array:

1 2 3 | // forceAwakens2 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} let intersetSet = forceAwakens2.interset(["Yoda", "C-3PO", "Han Solo"]) // intersectSet contains {"R2-D2", "Yoda"} |

You get the idea.

Now, although the `interset(_:)`

function returns a *new* set as a result we can also modify the *original* set, by using the `intersectInPlace(_:)`

function.

Where the `interset(_:)`

function returns a new set, the `intersectInPlace(_:)`

function modifies the set upon which the `intersect(_:)`

function is called. The result is that we can *only* call this function on mutable sets (i.e. those declared with the `var`

keyword).

Note: So that we don’t change our original set, I’ll make a copy of the `forceAwakens2`

set for use in this example:

1 2 3 4 5 | var forceAwakens3 = forceAwakens2 // forceAwakens3 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} forceAwakens3.intersectInPlace(returnOfTheJedi) // forceAwakens3 now contains {"Yoda", "Chewbacca", "C-3PO", "R2-D2"} |

As you can see, the contents of the `forceAwakens3`

set is modified to only contain the values that are common between the two sets.

### Union / Union in Place

The next pair of functions available on the `Set`

type in Swift are the `union(_:)`

and `unionInPlace(_:)`

functions. Diagrammatically, they can be represented as follows:

The `union(_:)`

function, returns a new function containing the elements from both the set on which the function is called *and* the functions parameter (again, any type that compiles with Swift’s `sequenceType`

protocol):

1 2 3 4 | // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} // forceAwakens2 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} let combinedSet = forceAwakens2.union(returnOfTheJedi) // combinedSet contains {"R2-D2", "BB-8", "Yoda", "Chewbacca", "C-3PO", "Darth Vader", "Finn"} |

In similar fashion to the `interset(_:)`

function, the `union(_:)`

also has a counterpart, the `unionInPlace(_:)`

function, which does the same thing, but instead of returning a *new* set, modifies the set on which the function is called:

1 2 3 4 5 | var forceAwakens4 = forceAwakens2 // forceAwakens4 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} forceAwakens4.unionInPlace(returnOfTheJedi) // forceAwakens4 contains {"R2-D2", "BB-8", "Yoda", "Chewbacca", "C-3PO", "Darth Vader", "Finn"} |

Now, remember way back at the start of this article when we were looking at how to add elements to an existing set? You might have guessed that We can use the `unionInPlace(_:)`

function to add multiple new elements to a set without having to all the `insert(_:)`

function multiple times:

1 2 | forceAwakens4.unionInPlace(["Kylo Ren", "Poe Dameron"]) // forceAwakens4 contains {"R2-D2", "Poe Dameron", "Kylo Ren", "BB-8", "Yoda", "Chewbacca", "C-3PO", "Darth Vader", "Finn"} |

Handy!

### Exclusive OR / Exclusive OR in Place

Next up are the `exclusiveOr(_:)`

and `exclusiveOrInPlace(_:)`

functions. These functions identify those elements that are in either the set upon which the function is called, *or* the set / sequence supplied as a parameter but are not present in both. This can be visualised as follows:

In terms of our Star Wars sets, this essentially means identifying those characters that are either in the `forceAwakens2`

set *or* the `returnOfTheJedi`

set but do not appear in both films:

1 2 3 4 | // forceAwakens2 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} let uniqueCharacters = forceAwakens2.exclusiveOr(returnOfTheJedi) // uniqueCharacters = {"Finn", "Darth Vader", "BB-8"} |

In similar fashion, we also have the `exclusiveOrInPlace(_:)`

function that does the same thing but modifies the original set:

1 2 3 4 5 | var forceAwakens5 = forceAwakens2 // forceAwakens5 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} forceAwakens5.exclusiveOrInPlace(returnOfTheJedi) // forceAwakens5 contains {"Finn", "Darth Vader", "BB-8"} |

### Subtract / Subtract In Place

Ok, we’re nearly there. Time for our last pair of functions, these are the `subtract(_:)`

and `subtractInPlace(_:)`

functions. These functions allow us to subtract the elements of one set or sequence from the elements of another. This can be illustrated as follows:

First, we have the `subtract(_:)`

function. As with all the other set functions we’ve looked at, it takes a single parameter of any type that complies with Swift’s `sequenceType`

protocol and removes the elements of that sequence from the set upon which the function is called:

1 2 3 4 | // forceAwakens2 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} let uniqueToForceAwakens = forceAwakens2.subtract(returnOfTheJedi) // uniqueToForceAwakens contains {"Finn", "BB-8"} |

Finally, we have the `subtractInPlace(_:)`

function. You can probably guess what this does by now:

1 2 3 4 5 | var forceAwakens6 = forceAwakens2 // forceAwakens6 contains {"Finn", "R2-D2", "Yoda", "Chewbacca", "C-3PO", "BB-8"} // returnOfTheJedi contains {"Chewbacca", "C-3PO", "R2-D2", "Yoda", "Darth Vader"} forceAwakens6.subtractInPlace(returnOfTheJedi) // forceAwakens6 contains {"Finn", "BB-8"} |

Ok, I think we’ve done Swift’s `Set`

type to death by now so we’ll wrap thing up there.

As ever, if you do have any questions (or if I’ve got anything wrong) please leave a comment using the form below and if you do find this useful, I’d really appreciate it if you share it with your friends.