Swift reverse a string word by word
Video: Swift reverse a string word by word by Taught by Celeste AI - AI Coding Coach
Swift with Copilot: Reverse a String Word by Word
str.split(separator: " ").reversed().joined(separator: " "). Three ops in one line: split, reverse, rejoin. The "reverse the words, not the letters" trick.
A common interview question. Two common confusions: reversing letters (olleh) vs reversing words (world hello). This is the latter.
The Copilot prompt
// Reverse a sentence word by word: "hello world" -> "world hello"
let sentence = "the quick brown fox"
Copilot completes:
let sentence = "the quick brown fox"
let reversed = sentence
.split(separator: " ")
.reversed()
.joined(separator: " ")
print(reversed)
// "fox brown quick the"
Walkthrough
split(separator: " ")
"the quick brown fox".split(separator: " ")
// ["the", "quick", "brown", "fox"]
split returns [Substring] — substrings reference the original string's storage (no copy). For most uses, treat them like [String].
By default, consecutive separators collapse and empty pieces are dropped:
"a b c".split(separator: " ")
// ["a", "b", "c"] — 3 elements
"a b c".split(separator: " ", omittingEmptySubsequences: false)
// ["a", "", "", "b", "", "", "c"] — 7 elements
For "split on any whitespace":
"hello\tworld\nfoo".split(whereSeparator: \.isWhitespace)
// ["hello", "world", "foo"]
\.isWhitespace is a KeyPath — concise way to pass "is this character whitespace?"
reversed()
[1, 2, 3].reversed()
// ReversedCollection<[Int]>([3, 2, 1])
Returns a lazy ReversedCollection. To convert to Array, wrap with Array(...). For our pipeline, we don't need to — joined accepts any sequence.
joined(separator:)
["world", "fox", "hello"].joined(separator: " ")
// "world fox hello"
joined() (no separator) concatenates without delimiter. joined(separator: ", ") puts the separator between.
For arrays of Substring:
let parts: [Substring] = ["a", "b", "c"]
let s = parts.joined(separator: "-")
// "a-b-c"
joined returns String regardless of input element type.
A function
extension String {
func reversedWords() -> String {
self.split(separator: " ")
.reversed()
.joined(separator: " ")
}
}
print("hello world".reversedWords())
// "world hello"
Now any String has .reversedWords(). Extensions are Swift's clean way to add behavior to existing types.
Edge cases
"".reversedWords() // ""
" ".reversedWords() // "" — whitespace dropped
" hello world ".reversedWords() // "world hello" — whitespace collapsed
"single".reversedWords() // "single"
If you need to preserve original whitespace exactly, split isn't right — use a regex.
Reverse letters (different problem)
let letters = String("hello".reversed())
// "olleh"
String.reversed() is letter reversal. String(...) materializes.
For Unicode-aware:
let s = "Hello 👋"
String(s.reversed()) // "👋 olleH" — emoji stays as one grapheme
Swift's Character is a grapheme cluster, so emoji and combining marks survive reversal correctly.
Sentence-aware (with punctuation)
"Hello, world!".split(separator: " ").reversed().joined(separator: " ")
// "world! Hello,"
Punctuation sticks to the words. For "drop punctuation":
let cleaned = "Hello, world!"
.components(separatedBy: CharacterSet.punctuationCharacters)
.joined()
// "Hello world"
cleaned.split(separator: " ").reversed().joined(separator: " ")
// "world Hello"
components(separatedBy:) is Foundation's older API; works the same.
Performance
split + reversed + joined is O(n) — linear in input length. For huge strings, this is fine. For loops processing millions of strings, profile first; usually no faster path exists.
Common stumbles
split returns Substring, not String. Most APIs accept Substring because it conforms to StringProtocol. If a function strictly wants String, do String(substring).
reversed() is lazy. It doesn't allocate. To materialize: Array(...). Or just chain to .joined(...) like our example.
Multiple consecutive spaces. Collapsed by default. Use omittingEmptySubsequences: false to preserve.
Reverse String directly. let r = "hi".reversed() is a ReversedCollection<String> — not a String. Wrap: String("hi".reversed()).
Reversing emoji. Works correctly because Swift treats grapheme clusters as one Character. Don't index into bytes.
What's next
Episode 8: Is 2023 a leap year? Calendar arithmetic.
Recap
split(separator: " ").reversed().joined(separator: " ") for word-reverse. split returns [Substring] (zero-copy). \.isWhitespace for any-whitespace split. String("hi".reversed()) for letter reverse — Unicode-aware. Extensions add reversedWords() to all strings. components(separatedBy:) is the Foundation alternative.
Next episode: leap years.