{"id":2722,"date":"2026-02-05T11:33:47","date_gmt":"2026-02-05T11:33:47","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2722"},"modified":"2026-02-05T11:33:47","modified_gmt":"2026-02-05T11:33:47","slug":"chapter-68-swift-sorting","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-68-swift-sorting\/","title":{"rendered":"Chapter 68: Swift Sorting"},"content":{"rendered":"<h3 dir=\"auto\">1. The Big Picture: What does \u201csorting\u201d mean in Swift?<\/h3>\n<p dir=\"auto\">Sorting means <strong>rearranging the elements<\/strong> of a collection so they appear in a specific order.<\/p>\n<p dir=\"auto\">Most common orders people want:<\/p>\n<ul dir=\"auto\">\n<li><strong>Ascending<\/strong> (small \u2192 big): 1, 3, 7, 12, 25<\/li>\n<li><strong>Descending<\/strong> (big \u2192 small): 25, 12, 7, 3, 1<\/li>\n<li><strong>Alphabetical<\/strong> (A \u2192 Z): Apple, Banana, Mango, Orange<\/li>\n<li><strong>Reverse alphabetical<\/strong> (Z \u2192 A)<\/li>\n<li><strong>Custom order<\/strong> (e.g. by priority, by distance, by recency, by user rating\u2026)<\/li>\n<\/ul>\n<p dir=\"auto\">Swift gives you <strong>very elegant and type-safe<\/strong> ways to sort.<\/p>\n<p dir=\"auto\">The two most important methods you will use <strong>every single day<\/strong>:<\/p>\n<ol dir=\"auto\">\n<li>sorted() \u2192 returns <strong>a new sorted array<\/strong> (original unchanged)<\/li>\n<li>sort() \u2192 <strong>sorts the array in place<\/strong> (modifies the original)<\/li>\n<\/ol>\n<h3 dir=\"auto\">2. The simplest &amp; most common cases<\/h3>\n<h4 dir=\"auto\">Case 1 \u2013 Sorting numbers (ascending by default)<\/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 scores = [78, 92, 65, 88, 45, 95, 72]\r\n\r\n\/\/ Returns a NEW sorted array (original unchanged)\r\nlet sortedAscending = scores.sorted()\r\nprint(sortedAscending)     \/\/ [45, 65, 72, 78, 88, 92, 95]\r\n\r\n\/\/ Sort in place (modifies original array)\r\nvar mutableScores = scores\r\nmutableScores.sort()\r\nprint(mutableScores)       \/\/ [45, 65, 72, 78, 88, 92, 95]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Descending order<\/strong> (very common):<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>let descending = scores.sorted(by: &gt;)          \/\/ [95, 92, 88, 78, 72, 65, 45]\r\n\r\n\/\/ or\r\nmutableScores.sort(by: &gt;)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Real tip<\/strong>: &gt; is actually a <strong>function<\/strong> (Int, Int) -&gt; Bool \u2014 that\u2019s why it works directly.<\/p>\n<h4 dir=\"auto\">Case 2 \u2013 Sorting strings (alphabetical)<\/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 names = [\"Rahul\", \"Priya\", \"Aarav\", \"Sneha\", \"Karan\", \"Meera\"]\r\n\r\nlet alphabetical = names.sorted()\r\n\/\/ [\"Aarav\", \"Karan\", \"Meera\", \"Priya\", \"Rahul\", \"Sneha\"]\r\n\r\nlet reverseAlpha = names.sorted(by: &gt;)\r\n\/\/ [\"Sneha\", \"Rahul\", \"Priya\", \"Meera\", \"Karan\", \"Aarav\"]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Case-insensitive sorting<\/strong> (very important in real apps):<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>let mixedCase = [\"apple\", \"Banana\", \"cherry\", \"Date\", \"apricot\"]\r\n\r\nlet caseInsensitive = mixedCase.sorted { $0.lowercased() &lt; $1.lowercased() }\r\n\/\/ [\"apple\", \"apricot\", \"Banana\", \"cherry\", \"Date\"]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">3. Sorting custom types (structs \/ classes) \u2014 this is where it gets really useful<\/h3>\n<p dir=\"auto\">Almost every real app needs to sort <strong>objects<\/strong>, not just numbers or strings.<\/p>\n<h4 dir=\"auto\">Step 1 \u2013 Make your type comparable (the cleanest way)<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>struct Student {\r\n    let name: String\r\n    let score: Int\r\n    let age: Int\r\n}\r\n\r\n\/\/ Make it Comparable \u2014 Swift will use &lt; operator\r\nextension Student: Comparable {\r\n    static func &lt; (lhs: Student, rhs: Student) -&gt; Bool {\r\n        lhs.score &lt; rhs.score   \/\/ sort by score ascending\r\n        \/\/ You can add more rules:\r\n        \/\/ lhs.score != rhs.score ? lhs.score &lt; rhs.score : lhs.age &lt; rhs.age\r\n    }\r\n}\r\n\r\nlet students = [\r\n    Student(name: \"Rahul\", score: 920, age: 19),\r\n    Student(name: \"Priya\", score: 980, age: 18),\r\n    Student(name: \"Aarav\", score: 850, age: 20),\r\n    Student(name: \"Sneha\", score: 950, age: 17)\r\n]\r\n\r\n\/\/ Now you can sort naturally\r\nlet sortedByScore = students.sorted()\r\nprint(\"Sorted by score (ascending):\")\r\nfor s in sortedByScore {\r\n    print(\"  \\(s.name) - \\(s.score) points, age \\(s.age)\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Output:<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>text<\/div>\n<div>\n<pre tabindex=\"0\"><code>Sorted by score (ascending):\r\n  Aarav - 850 points, age 20\r\n  Rahul - 920 points, age 19\r\n  Sneha - 950 points, age 17\r\n  Priya - 980 points, age 18<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Step 2 \u2013 Sort by multiple criteria (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>let sortedByScoreThenAge = students.sorted { a, b in\r\n    if a.score != b.score {\r\n        return a.score &gt; b.score          \/\/ higher score first\r\n    }\r\n    return a.age &lt; b.age                  \/\/ if scores equal \u2192 younger first\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Shorter version<\/strong> (using tuple comparison):<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>let sorted = students.sorted {\r\n    ($0.score, $0.age) &gt; ($1.score, $1.age)   \/\/ descending score, then ascending age\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">4. Real-life examples you will actually write<\/h3>\n<h4 dir=\"auto\">Example 1 \u2013 Leaderboard \/ high scores (games, quizzes)<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>struct ScoreEntry {\r\n    let player: String\r\n    let points: Int\r\n    let date: Date\r\n}\r\n\r\nlet leaderboard = [\r\n    ScoreEntry(player: \"Rahul\",   points: 920, date: Date()),\r\n    ScoreEntry(player: \"Priya\",   points: 980, date: Date()),\r\n    ScoreEntry(player: \"Aarav\",   points: 850, date: Date()),\r\n    ScoreEntry(player: \"Sneha\",   points: 950, date: Date())\r\n]\r\n\r\n\/\/ Sort descending by points, then by date (newest first if tie)\r\nlet ranked = leaderboard.sorted { a, b in\r\n    if a.points != b.points {\r\n        return a.points &gt; b.points\r\n    }\r\n    return a.date &gt; b.date\r\n}\r\n\r\nprint(\"\ud83c\udfc6 Leaderboard\")\r\nfor (position, entry) in ranked.enumerated() {\r\n    let rank = position + 1\r\n    let rankSymbol = rank == 1 ? \"\ud83e\udd47\" : rank == 2 ? \"\ud83e\udd48\" : rank == 3 ? \"\ud83e\udd49\" : \"\\(rank).\"\r\n    print(\"\\(rankSymbol) \\(entry.player) - \\(entry.points) pts\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Example 2 \u2013 Sort products by price, then by name<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>struct Product {\r\n    let name: String\r\n    let price: Double\r\n}\r\n\r\nlet products = [\r\n    Product(name: \"Earbuds Pro\", price: 24999),\r\n    Product(name: \"Phone Case\",  price: 999),\r\n    Product(name: \"Charger\",     price: 2499),\r\n    Product(name: \"Earbuds\",     price: 9999)\r\n]\r\n\r\nlet sortedProducts = products.sorted { a, b in\r\n    if a.price != b.price {\r\n        return a.price &lt; b.price          \/\/ cheapest first\r\n    }\r\n    return a.name &lt; b.name                \/\/ if price equal \u2192 alphabetical\r\n}\r\n\r\nprint(\"Products sorted by price, then name:\")\r\nfor p in sortedProducts {\r\n    print(\"  \u20b9\\(String(format: \"%.0f\", p.price)) \u2013 \\(p.name)\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Very Common Beginner Mistakes &amp; Fixes<\/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=\"lg\">Correct \/ Better habit<\/th>\n<th data-col-size=\"lg\">Why?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Mutating array while sorting<\/td>\n<td data-col-size=\"lg\">array.sort { \u2026 } then keep using old reference<\/td>\n<td data-col-size=\"lg\">let sorted = array.sorted { \u2026 }<\/td>\n<td data-col-size=\"lg\">sort() mutates, sorted() returns new<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Force-unwrapping inside sort closure<\/td>\n<td data-col-size=\"lg\">sorted { $0!.score &lt; $1!.score }<\/td>\n<td data-col-size=\"lg\">Use compactMap first or optional chaining<\/td>\n<td data-col-size=\"lg\">Crash if any nil<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Sorting optional values without handling nil<\/td>\n<td data-col-size=\"lg\">sorted { $0 &lt; $1 } on [Int?]<\/td>\n<td data-col-size=\"lg\">sorted { $0 ?? 0 &lt; $1 ?? 0 } or filter nils<\/td>\n<td data-col-size=\"lg\">nil crashes comparison<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Wrong comparator direction<\/td>\n<td data-col-size=\"lg\">sorted { $0.score &lt; $1.score } for descending<\/td>\n<td data-col-size=\"lg\">sorted { $0.score &gt; $1.score }<\/td>\n<td data-col-size=\"lg\">Easy to mix up ascending\/descending<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Not using sorted(by:) when logic is complex<\/td>\n<td data-col-size=\"lg\">sorted() on custom type<\/td>\n<td data-col-size=\"lg\">sorted { a, b in \u2026 } with clear rules<\/td>\n<td data-col-size=\"lg\">Default Comparable may not be what you want<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">6. Quick Reference \u2013 Sorting cheat sheet<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"md\">Goal<\/th>\n<th data-col-size=\"lg\">Most idiomatic code<\/th>\n<th data-col-size=\"lg\">Notes \/ Tip<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"md\">Numbers ascending<\/td>\n<td data-col-size=\"lg\">array.sorted() or array.sorted(by: &lt;)<\/td>\n<td data-col-size=\"lg\">Default is ascending<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Numbers descending<\/td>\n<td data-col-size=\"lg\">array.sorted(by: &gt;)<\/td>\n<td data-col-size=\"lg\">Very common<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Strings case-insensitive<\/td>\n<td data-col-size=\"lg\">sorted { $0.lowercased() &lt; $1.lowercased() }<\/td>\n<td data-col-size=\"lg\">Handles &#8220;Apple&#8221; vs &#8220;banana&#8221; correctly<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Custom struct by one property<\/td>\n<td data-col-size=\"lg\">sorted { $0.score &gt; $1.score }<\/td>\n<td data-col-size=\"lg\">Descending score<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Custom struct by multiple properties<\/td>\n<td data-col-size=\"lg\">sorted { ($0.score, $0.age) &gt; ($1.score, $1.age) }<\/td>\n<td data-col-size=\"lg\">Score descending, then age ascending<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Keep original unchanged<\/td>\n<td data-col-size=\"lg\">let sorted = array.sorted { \u2026 }<\/td>\n<td data-col-size=\"lg\">sorted() returns new array<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">Sort in place (modify original)<\/td>\n<td data-col-size=\"lg\">array.sort { \u2026 }<\/td>\n<td data-col-size=\"lg\">Use only when you don\u2019t need the old order<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">7. Small Practice \u2013 Try these<\/h3>\n<ol dir=\"auto\">\n<li>Create array of 6 numbers \u2192 Sort them ascending \u2192 Sort them descending<\/li>\n<li>Create array of 5 names (mixed case) \u2192 Sort them alphabetically (case-insensitive)<\/li>\n<li>Create array of structs: struct Product { let name: String; let price: Double } \u2192 Sort by price ascending, then by name alphabetical if prices equal<\/li>\n<\/ol>\n<p dir=\"auto\">Paste your code here if you want feedback or want to see even cleaner versions!<\/p>\n<p dir=\"auto\">What would you like to explore next?<\/p>\n<ul dir=\"auto\">\n<li><strong>Sorting<\/strong> with <strong>multiple criteria<\/strong> in more depth<\/li>\n<li><strong>Sorting<\/strong> custom types with Comparable conformance<\/li>\n<li><strong>Sorting<\/strong> in <strong>SwiftUI<\/strong> (sorted lists, @State updates)<\/li>\n<li><strong>Array slicing<\/strong> &amp; memory behavior<\/li>\n<li>Collections in <strong>SwiftUI<\/strong> (List, ForEach, diffable data sources)<\/li>\n<li>Or move to another topic (dictionaries, sets, optionals, switch\u2026)<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me \u2014 we\u2019ll continue in the same clear, detailed, patient style \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. The Big Picture: What does \u201csorting\u201d mean in Swift? Sorting means rearranging the elements of a collection so they appear in a specific order. Most common orders people want: Ascending (small \u2192 big):&#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-2722","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2722","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=2722"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2722\/revisions"}],"predecessor-version":[{"id":2723,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2722\/revisions\/2723"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2722"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2722"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2722"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}