{"id":2716,"date":"2026-02-05T11:17:45","date_gmt":"2026-02-05T11:17:45","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2716"},"modified":"2026-02-05T11:17:45","modified_gmt":"2026-02-05T11:17:45","slug":"chapter-65-swift-sets","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-65-swift-sets\/","title":{"rendered":"Chapter 65: Swift Sets"},"content":{"rendered":"<h3 dir=\"auto\">1. The most important intuition: What problem does a Set solve?<\/h3>\n<p dir=\"auto\">A <strong>Set<\/strong> is a collection that guarantees <strong>only unique values<\/strong> \u2014 no duplicates allowed \u2014 and gives you <strong>very fast \u201cdoes this contain X?\u201d<\/strong> answers.<\/p>\n<p dir=\"auto\">Think of it as:<\/p>\n<ul dir=\"auto\">\n<li>A <strong>guest list<\/strong> for a party where <strong>nobody can enter twice<\/strong><\/li>\n<li>A <strong>collection of tags<\/strong> on a blog post (you never want \u201cswift, swift, ios\u201d)<\/li>\n<li>A <strong>set of permissions<\/strong> a user has (\u201cread\u201d, \u201cwrite\u201d, \u201cdelete\u201d \u2014 no duplicates)<\/li>\n<li>A <strong>collection of unique user IDs<\/strong> in a group chat<\/li>\n<\/ul>\n<p dir=\"auto\">Key differences from Array:<\/p>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"md\">Feature<\/th>\n<th data-col-size=\"lg\">Array [T]<\/th>\n<th data-col-size=\"lg\">Set &lt;T&gt;<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"md\">Order<\/td>\n<td data-col-size=\"lg\">Yes (keeps the order you add things)<\/td>\n<td data-col-size=\"lg\"><strong>No<\/strong> \u2014 order is not guaranteed<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Duplicates<\/td>\n<td data-col-size=\"lg\">Allowed<\/td>\n<td data-col-size=\"lg\"><strong>Not allowed<\/strong> \u2014 duplicates ignored<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Fast \u201ccontains X?\u201d<\/td>\n<td data-col-size=\"lg\">Slow \u2014 must look through all items<\/td>\n<td data-col-size=\"lg\"><strong>Very fast<\/strong> \u2014 uses hashing<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Can I get element by index?<\/td>\n<td data-col-size=\"lg\">Yes \u2014 array[3]<\/td>\n<td data-col-size=\"lg\"><strong>No<\/strong> \u2014 no indices<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Typical real question<\/td>\n<td data-col-size=\"lg\">\u201cWhat is the 5th item?\u201d<\/td>\n<td data-col-size=\"lg\">\u201cDoes this user have permission X?\u201d<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Golden rule you should memorize forever:<\/strong><\/p>\n<blockquote dir=\"auto\">\n<p dir=\"auto\">If <strong>order matters<\/strong> or <strong>duplicates are okay<\/strong> \u2192 use Array If <strong>uniqueness is required<\/strong> and you often ask \u201cis X in the collection?\u201d \u2192 use Set<\/p>\n<\/blockquote>\n<h3 dir=\"auto\">2. Creating Sets \u2013 the most common ways<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>\/\/ 1. Literal syntax (most readable for small sets)\r\nvar colors = Set&lt;String&gt;()\r\ncolors.insert(\"Red\")\r\ncolors.insert(\"Green\")\r\ncolors.insert(\"Blue\")\r\ncolors.insert(\"Red\")           \/\/ ignored \u2013 duplicate\r\n\r\n\/\/ 2. From array (very common \u2013 remove duplicates)\r\nlet tagsArray = [\"swift\", \"ios\", \"swift\", \"beginner\", \"swiftui\"]\r\nlet uniqueTags = Set(tagsArray)   \/\/ Set([\"swift\", \"ios\", \"beginner\", \"swiftui\"])\r\n\r\n\/\/ 3. Empty set with type annotation\r\nvar activeUsers: Set&lt;Int&gt; = []\r\n\r\n\/\/ 4. From other collections\r\nlet numbers = [1, 2, 2, 3, 3, 4]\r\nlet uniqueNumbers = Set(numbers)   \/\/ Set([1, 2, 3, 4])<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">3. Most important Set operations (you will use these every day)<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>var permissions = Set&lt;String&gt;()\r\n\r\n\/\/ Add\r\npermissions.insert(\"read\")\r\npermissions.insert(\"write\")\r\npermissions.insert(\"moderate\")\r\n\r\n\/\/ Check contains (very fast!)\r\nprint(permissions.contains(\"write\"))      \/\/ true\r\nprint(permissions.contains(\"delete\"))     \/\/ false\r\n\r\n\/\/ Remove\r\npermissions.remove(\"moderate\")\r\n\r\n\/\/ Count &amp; empty\r\nprint(permissions.count)                  \/\/ 2\r\nprint(permissions.isEmpty)                \/\/ false\r\n\r\n\/\/ Combine sets\r\nlet adminExtras = Set([\"delete\", \"ban\", \"edit\"])\r\nlet allPermissions = permissions.union(adminExtras)\r\n\r\n\/\/ Intersection (common permissions)\r\nlet shared = permissions.intersection(adminExtras)\r\n\r\n\/\/ Difference (what admin has extra)\r\nlet adminOnly = adminExtras.subtracting(permissions)\r\n\r\n\/\/ Symmetric difference (items in one but not both)\r\nlet different = permissions.symmetricDifference(adminExtras)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">4. Real-life examples \u2014 code you will actually write<\/h3>\n<h4 dir=\"auto\">Example 1 \u2013 User permissions \/ roles (very common)<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>var currentUserRoles = Set&lt;String&gt;()\r\n\r\n\/\/ Load from server \/ token\r\ncurrentUserRoles.insert(\"user\")\r\ncurrentUserRoles.insert(\"moderator\")\r\ncurrentUserRoles.insert(\"user\")         \/\/ ignored\r\n\r\n\/\/ Check capabilities\r\nif currentUserRoles.contains(\"moderator\") {\r\n    print(\"User can moderate posts\")\r\n}\r\n\r\nif currentUserRoles.isSuperset(of: [\"user\", \"moderator\"]) {\r\n    print(\"User has both user and moderator rights\")\r\n}\r\n\r\n\/\/ Add new role\r\ncurrentUserRoles.insert(\"admin\")\r\n\r\n\/\/ Remove role\r\ncurrentUserRoles.remove(\"user\")<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Example 2 \u2013 Unique tags \/ categories (blog, photo app, product filters)<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>var selectedTags = Set&lt;String&gt;()\r\n\r\nfunc toggleTag(_ tag: String) {\r\n    if selectedTags.contains(tag) {\r\n        selectedTags.remove(tag)\r\n        print(\"Tag removed: \\(tag)\")\r\n    } else {\r\n        selectedTags.insert(tag)\r\n        print(\"Tag added: \\(tag)\")\r\n    }\r\n}\r\n\r\ntoggleTag(\"Swift\")\r\ntoggleTag(\"iOS\")\r\ntoggleTag(\"Swift\")      \/\/ does nothing \u2014 already present\r\ntoggleTag(\"Beginner\")\r\n\r\nprint(\"Active filters:\", selectedTags)\r\n\/\/ Active filters: Set([\"Swift\", \"iOS\", \"Beginner\"])<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Example 3 \u2013 Remove duplicates from user input<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>let userEnteredEmails = [\r\n    \"rahul@example.com\",\r\n    \"priya@gmail.com\",\r\n    \"rahul@example.com\",\r\n    \"aarav@work.com\",\r\n    \"priya@gmail.com\"\r\n]\r\n\r\nlet uniqueEmails = Set(userEnteredEmails)\r\n\r\nprint(\"Unique email addresses:\")\r\nfor email in uniqueEmails {\r\n    print(\"  \u2022 \\(email)\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Example 4 \u2013 Check required permissions before action<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>let requiredPermissions: Set&lt;String&gt; = [\"read\", \"write\", \"moderate\"]\r\n\r\nlet userHas = Set([\"read\", \"write\"])\r\n\r\nif userHas.isSuperset(of: requiredPermissions) {\r\n    print(\"User has all required permissions\")\r\n} else {\r\n    let missing = requiredPermissions.subtracting(userHas)\r\n    print(\"Missing permissions: \\(missing)\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Very Common Beginner Mistakes &amp; Correct Habits<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">Mistake<\/th>\n<th data-col-size=\"lg\">Wrong \/ Dangerous code<\/th>\n<th data-col-size=\"md\">Correct \/ Better habit<\/th>\n<th data-col-size=\"sm\">Why?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Expecting order in Set<\/td>\n<td data-col-size=\"lg\">print(mySet) assuming order<\/td>\n<td data-col-size=\"md\">Never rely on order in Set<\/td>\n<td data-col-size=\"sm\">Sets are unordered (can change)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Using Set when order matters<\/td>\n<td data-col-size=\"lg\">let steps = Set([&#8220;step1&#8221;, &#8220;step2&#8221;])<\/td>\n<td data-col-size=\"md\">Use Array when order is important<\/td>\n<td data-col-size=\"sm\">Set will lose order<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Using Set when duplicates are allowed<\/td>\n<td data-col-size=\"lg\">let cart = Set([&#8220;milk&#8221;, &#8220;bread&#8221;, &#8220;milk&#8221;])<\/td>\n<td data-col-size=\"md\">Use Array for shopping cart<\/td>\n<td data-col-size=\"sm\">Set removes duplicates<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Forgetting Set is value type<\/td>\n<td data-col-size=\"lg\">var a = b; a.insert(&#8220;x&#8221;) \u2192 b changes?<\/td>\n<td data-col-size=\"md\">No \u2014 a is copy, b unchanged<\/td>\n<td data-col-size=\"sm\">Value type safety<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Checking contains with Array instead of Set<\/td>\n<td data-col-size=\"lg\">array.contains(&#8220;tag&#8221;) in hot path<\/td>\n<td data-col-size=\"md\">Convert to Set if you check contains often<\/td>\n<td data-col-size=\"sm\">Array is O(n), Set is O(1)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">6. Quick Summary \u2013 When to choose Set vs Array vs Dictionary<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">You want to\u2026<\/th>\n<th data-col-size=\"sm\">Choose this<\/th>\n<th data-col-size=\"lg\">Typical real-life sentence<\/th>\n<th data-col-size=\"xl\">Example real use-case<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Keep order, allow duplicates<\/td>\n<td data-col-size=\"sm\">Array<\/td>\n<td data-col-size=\"lg\">\u201cI have a list of things in order\u201d<\/td>\n<td data-col-size=\"xl\">shopping cart, messages, tasks, search results<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Ensure uniqueness, fast \u201ccontains?\u201d<\/td>\n<td data-col-size=\"sm\">Set<\/td>\n<td data-col-size=\"lg\">\u201cI have a group of unique items\u201d<\/td>\n<td data-col-size=\"xl\">tags, permissions, unique IDs, friends (no dupes)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Fast lookup by key<\/td>\n<td data-col-size=\"sm\">Dictionary<\/td>\n<td data-col-size=\"lg\">\u201cI want to find value by name\/ID\u201d<\/td>\n<td data-col-size=\"xl\">user profile, settings, JSON, config<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">7. Small Practice \u2013 Try these right now<\/h3>\n<ol dir=\"auto\">\n<li>Create a <strong>Set<\/strong> of 6 tags (add some duplicates on purpose) \u2192 Print how many unique tags you have \u2192 Check if &#8220;Swift&#8221; is present \u2192 Add 2 more tags \u2192 Remove one tag<\/li>\n<li>Create array of 10 email addresses (some duplicates) \u2192 Convert to Set to get unique emails \u2192 Print how many unique emails were found<\/li>\n<li>Create a <strong>Set<\/strong> of user roles\/permissions \u2192 Check if user has both &#8220;read&#8221; and &#8220;write&#8221; \u2192 Check if user has &#8220;admin&#8221; or &#8220;moderator&#8221;<\/li>\n<\/ol>\n<p dir=\"auto\">Paste your code here if you want feedback, corrections, or more polished versions!<\/p>\n<p dir=\"auto\">What would you like to explore next?<\/p>\n<ul dir=\"auto\">\n<li><strong>Set operations<\/strong> in depth (union, intersection, difference, symmetric difference)<\/li>\n<li><strong>Array slicing<\/strong> &amp; memory behavior<\/li>\n<li><strong>Sorting<\/strong> arrays (simple &amp; custom comparators)<\/li>\n<li><strong>Dictionaries<\/strong> in depth (typed keys, default values)<\/li>\n<li>Collections in <strong>SwiftUI<\/strong> (List, ForEach, @State)<\/li>\n<li>Or move to another topic (optionals, switch, functions\u2026)<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me \u2014 we\u2019ll continue in the same clear, patient, detailed style \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. The most important intuition: What problem does a Set solve? A Set is a collection that guarantees only unique values \u2014 no duplicates allowed \u2014 and gives you very fast \u201cdoes this contain&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[76],"tags":[],"class_list":["post-2716","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2716","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/comments?post=2716"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2716\/revisions"}],"predecessor-version":[{"id":2717,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2716\/revisions\/2717"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}