'How to return a first word from a string in Swift?
If we have, for example, situation like this:
var myString = "Today was a good day"
What is the best way to return the first word, which is "Today"? I think mapping should be applied, but not sure how.
Thanks.
Solution 1:[1]
The simplest way I can think of is
Swift 3
let string = "hello world"
let firstWord = string.components(separatedBy: " ").first
Swift 2.2
let string = "hello world"
let firstWord = string.componentsSeparatedByString(" ").first
and if you think you need to use it a lot in your code, make it as an extension
extension String {
func firstWord() -> String? {
return self.components(separatedBy: " ").first
}
}
Usage
let string = "hello world"
let firstWord = string.firstWord()
Solution 2:[2]
You can use StringProtocol method enumerateSubstrings(in: Range<String.Index>) with options .byWords to enumerate the words in your string and just get the first element:
Swift 5.1 • Xcode 11 or later
Note: For older Swift syntax check this post edit history
import Foundation
extension StringProtocol {
var byLines: [SubSequence] { components(separated: .byLines) }
var byWords: [SubSequence] { components(separated: .byWords) }
func components(separated options: String.EnumerationOptions)-> [SubSequence] {
var components: [SubSequence] = []
enumerateSubstrings(in: startIndex..., options: options) { _, range, _, _ in components.append(self[range]) }
return components
}
var firstWord: SubSequence? {
var word: SubSequence?
enumerateSubstrings(in: startIndex..., options: .byWords) { _, range, _, stop in
word = self[range]
stop = true
}
return word
}
var firstLine: SubSequence? {
var line: SubSequence?
enumerateSubstrings(in: startIndex..., options: .byLines) { _, range, _, stop in
line = self[range]
stop = true
}
return line
}
}
Playground Testing:
let string = "• Today was a good day.\n• Tomorrow will be better.\n"
let firstWord = string.firstWord // "Today"
let firstLine = string.firstLine // "• Today was a good day."
let firstLineLastWord = string.firstLine?.byWords.last // day
let firstLineLast2Words = string.firstLine?.byWords.suffix(2) // ["good", "day"]
Solution 3:[3]
I would prefer using CharacterSet, since words can be delimited by white-spaces as well as punctuation marks.
var myString = "Today was a good day"
let nonLetters = CharacterSet.letters.inverted
let first = myString.components(separatedBy: nonLetters).first
Solution 4:[4]
To avoid processing the whole string just to get the first word, you could do this:
let string = "Hello World"
let word1 = string.prefix{ (c:Character) in CharacterSet.letters.contains(c.unicodeScalars.first!) }
Solution 5:[5]
Try using prefix() function
let string = "Today was a good day"
if let spaceIndex = string.firstIndex(of: " ") {
let firstWord = String(string.prefix(upTo: string.index(after: spaceIndex)))
print(firstWord) // Today
}
Solution 6:[6]
Elegant solution:
extension String {
var firstWord: String {
self.components(separatedBy: " ").first ?? ""
}
}
Usage:
let myString = "Today was a good day"
print(myString.firstWord)
output:
Today
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Vinod Vishwanath |
| Solution 4 | Alain T. |
| Solution 5 | Rachit Agarwal |
| Solution 6 | Ali Hamad |
