Leave a rating/review
Notes: 31. Working with Sets
Update Notes: The student materials have been reviewed and are updated as of October 2021.
In this exercise, you’ll learn about a third and final collection type in Swift: sets.
A set is an unordered collection of unique values of the same type. For example, here’s a set of Swift birds holding different items - like a game controller, a frying pan with an egg, or an iPhone.
What do I mean by “a collection of unique values”, though? Well, we can insert a Swift bird holding a cat into this set and that would work! We don’t have this image in our collection yet.
But if we tried to insert another copy of the Swift bird holding the controller. Well, nothing would happen. That images is already in the collection, and sets can only store unique values. Another way to say that is “sets don’t store duplicate values”.
This can be extremely useful when you want to ensure that an item doesn’t appear more than once in your collection. You can also use sets when the order of your items isn’t important.
Let’s see how you can use sets in Swift, and how they differ from dictionaries.
Creating a set is a little bit different than creating a array or a dictionary in Swift. To create a set called someSet, we have to say Set and then add the type inside angle brackets.
var someSet: Set<Int>
You can create Arrays and Dictionaries with a similar looking syntax, actually. But both Array and Dictionary have a shorthand syntax, and that’s what we’ve been using.
//let someArray: Array<Int>
//let someDictionary: Dictionary<String, Int>
Sets just don’t have a short option. You have to explicitly declare them in this form. If you want to initialize the set with some values, that part will look exactly like an array:
var someSet: Set<Int> = [1, 2, 3, 1]
And now we have a set of Ints! But - I said sets can’t contain duplicate values.
-
So if you check the results on the right, you’ll only see a single “1” even though we tried to add the number “1” to the set twice.
-
When you try to add a duplicate value to a set, Swift simply ignores the duplicate value.
To find out if a set already contains a certain value, you can use the contains method! Just pass in the value you want to check for,
someSet.contains(1)
- and you’ll get a boolean as a result. This set does contain “1”, so we get true.
But if we check the set for 99…
someSet.contains(99)
- We’ll get false, because 99 is not in the set.
If you want to add elements to a set, the insert method is what you’re looking for.
- Because sets aren’t ordered, you don’t need to specify where you’re inserting the new value, you just pass the value in as the only argument.
someSet.insert(5)
Now 5 is part of the set! You can only do this because you’ve declared the set as a variable. If you have a set that’s a constant, you can’t add or remove elements.
-
When you do have a variable, like yours here, removing elements is just as easy as adding them. You just use the
removemethod, instead.
someSet.remove(3)
- The remove method actually returns the removed element. If you wanted to store the element you’re removing into a new variable or constant, that’s easy to do!
let removedElement = someSet.remove(3)
- If it turned out that the value wasn’t in your set, you’d get nil instead of a value.
let nilElement = someSet.remove(42)
And you can see that Swift returns nil here, to tell me that there was no result from this removal operation. So just like with dictionaries, you should use some form of optional binding if you want to use that value.
-
To see what’s in our set, now, just type
someSetand check the sidebar.
someSet
You’ve successfully added 5 and removed 3, leaving you with a set of 5, 1, and 2. Sets are unordered, so you may see these values in a different order than I do.
- In fact, if I run the playground again, we’ll probably see them in a different order, too!
There’s one more handy thing we’ll show you about sets, and that’s how to compare them with other sets.
- First, I’ll create another set with at least one value that exists in the first set, and at least one that doesn’t.
let anotherSet: Set<Int> = [5, 7, 13]
Now there’s a few handy methods you can use to create new sets by comparing the two you already have.
- You can make a set that only contains elements found in both sets.
let intersection = someSet.intersection(anotherSet)
-
That’s called “intersection”. There’s also
symmetricDifference, which does the exact opposite ofintersection. It returns only the elements that are not in both sets.
let difference = someSet.symmetricDifference(anotherSet)
-
And the last one is
union. This method returns all of the elements in both sets.
let union = someSet.union(anotherSet)
- Again, because these are sets, you’ll only have one element in the set for any duplicate values. For example, we only have one “5” in the set.
These methods all return a new set resulting from each particular operation. But what if you actually want to change one of the sets, in-place, in relation to another set?
- There are alternate versions of each of these methods, that will change, or mutate, the set you call it on, instead of returning a new set.
These alternate versions all begin with the word “form”.
someSet.form
-
Try using “formUnion” on
someSetand pass inanotherSet, again, as the argument.
someSet.formUnion(anotherSet)
-
Now if you look at each of those sets, you’ll see that someSet has mutated to include all elements from both sets.
anotherSet, however, hasn’t changed at all. Only the set you call the method on will change. The set you pass in as an argument won’t be affected.
someSet
anotherSet
That’s all I want to show you about sets; head on into the next video for a “set” of challenges on, of course, sets!