Get nth character of a string in Swift programming language
Attention: Please see Leo Dabus' answer for a proper implementation for Swift 4 and Swift 5.
Swift 4 or later
The Substring
type was introduced in Swift 4 to make substrings
faster and more efficient by sharing storage with the original string, so that's what the subscript functions should return.
Try it out here
extension StringProtocol {
subscript(offset: Int) -> Character { self[index(startIndex, offsetBy: offset)] }
subscript(range: Range<Int>) -> SubSequence {
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
return self[startIndex..<index(startIndex, offsetBy: range.count)]
}
subscript(range: ClosedRange<Int>) -> SubSequence {
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
return self[startIndex..<index(startIndex, offsetBy: range.count)]
}
subscript(range: PartialRangeFrom<Int>) -> SubSequence { self[index(startIndex, offsetBy: range.lowerBound)...] }
subscript(range: PartialRangeThrough<Int>) -> SubSequence { self[...index(startIndex, offsetBy: range.upperBound)] }
subscript(range: PartialRangeUpTo<Int>) -> SubSequence { self[..<index(startIndex, offsetBy: range.upperBound)] }
}
To convert the Substring
into a String
, you can simply
do String(string[0..2])
, but you should only do that if
you plan to keep the substring around. Otherwise, it's more
efficient to keep it a Substring
.
It would be great if someone could figure out a good way to merge Note: This answer has been already edited, it is properly implemented and now works for substrings as well. Just make sure to use a valid range to avoid crashing when subscripting your StringProtocol type. For subscripting with a range that won't crash with out of range values you can use this implementation
these two extensions into one. I tried extending StringProtocol
without success, because the index
method does not exist there.
Why is this not built-in?
The error message says "see the documentation comment for discussion". Apple provides the following explanation in the file UnavailableStringAPIs.swift:
Subscripting strings with integers is not available.
The concept of "the
i
th character in a string" has
different interpretations in different libraries and system
components. The correct interpretation should be selected
according to the use case and the APIs involved, soString
cannot be subscripted with an integer.Swift provides several different ways to access the character
data stored inside strings.
String.utf8
is a collection of UTF-8 code units in the
string. Use this API when converting the string to UTF-8.
Most POSIX APIs process strings in terms of UTF-8 code units.
String.utf16
is a collection of UTF-16 code units in
string. Most Cocoa and Cocoa touch APIs process strings in
terms of UTF-16 code units. For example, instances of
NSRange
used withNSAttributedString
and
NSRegularExpression
store substring offsets and lengths in
terms of UTF-16 code units.
String.unicodeScalars
is a collection of Unicode scalars.
Use this API when you are performing low-level manipulation
of character data.
String.characters
is a collection of extended grapheme
clusters, which are an approximation of user-perceived
characters.
Note that when processing strings that contain human-readable text,
character-by-character processing should be avoided to the largest extent
possible. Use high-level locale-sensitive Unicode algorithms instead, for example,
String.localizedStandardCompare()
,
String.localizedLowercaseString
,
String.localizedStandardRangeOfString()
etc.
Get nth character of a string in Swift programming language
Attention: Please see Leo Dabus' answer for a proper implementation for Swift 4 and Swift 5.
Swift 4 or later
The Substring
type was introduced in Swift 4 to make substrings
faster and more efficient by sharing storage with the original string, so that's what the subscript functions should return.
Try it out here
extension StringProtocol {
subscript(offset: Int) -> Character { self[index(startIndex, offsetBy: offset)] }
subscript(range: Range<Int>) -> SubSequence {
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
return self[startIndex..<index(startIndex, offsetBy: range.count)]
}
subscript(range: ClosedRange<Int>) -> SubSequence {
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
return self[startIndex..<index(startIndex, offsetBy: range.count)]
}
subscript(range: PartialRangeFrom<Int>) -> SubSequence { self[index(startIndex, offsetBy: range.lowerBound)...] }
subscript(range: PartialRangeThrough<Int>) -> SubSequence { self[...index(startIndex, offsetBy: range.upperBound)] }
subscript(range: PartialRangeUpTo<Int>) -> SubSequence { self[..<index(startIndex, offsetBy: range.upperBound)] }
}
To convert the Substring
into a String
, you can simply
do String(string[0..2])
, but you should only do that if
you plan to keep the substring around. Otherwise, it's more
efficient to keep it a Substring
.
It would be great if someone could figure out a good way to merge Note: This answer has been already edited, it is properly implemented and now works for substrings as well. Just make sure to use a valid range to avoid crashing when subscripting your StringProtocol type. For subscripting with a range that won't crash with out of range values you can use this implementation
these two extensions into one. I tried extending StringProtocol
without success, because the index
method does not exist there.
Why is this not built-in?
The error message says "see the documentation comment for discussion". Apple provides the following explanation in the file UnavailableStringAPIs.swift:
Subscripting strings with integers is not available.
The concept of "the
i
th character in a string" has
different interpretations in different libraries and system
components. The correct interpretation should be selected
according to the use case and the APIs involved, soString
cannot be subscripted with an integer.Swift provides several different ways to access the character
data stored inside strings.
String.utf8
is a collection of UTF-8 code units in the
string. Use this API when converting the string to UTF-8.
Most POSIX APIs process strings in terms of UTF-8 code units.
String.utf16
is a collection of UTF-16 code units in
string. Most Cocoa and Cocoa touch APIs process strings in
terms of UTF-16 code units. For example, instances of
NSRange
used withNSAttributedString
and
NSRegularExpression
store substring offsets and lengths in
terms of UTF-16 code units.
String.unicodeScalars
is a collection of Unicode scalars.
Use this API when you are performing low-level manipulation
of character data.
String.characters
is a collection of extended grapheme
clusters, which are an approximation of user-perceived
characters.
Note that when processing strings that contain human-readable text,
character-by-character processing should be avoided to the largest extent
possible. Use high-level locale-sensitive Unicode algorithms instead, for example,
String.localizedStandardCompare()
,
String.localizedLowercaseString
,
String.localizedStandardRangeOfString()
etc.
Access a char in a string, Swift 3.x
Its pretty simple :
let myText = Array("Hello World !!!".characters)
print(myText[2]) // "l" will be printed
How to get the coordinates (x,y) of a character in a String
Your Swift syntax is really old (Swift 2). Change range.startIndex
to range.lowerBound
. substringToIndex
is now called substring(to: Index) but it is deprecated, you should use subscript self[..<range.lowerBound]
. Btw there is no need to use String range(of: String)
if you are looking for a index of a character. You can use collection method firstIndex(of: Element)
:
extension StringProtocol {
func characterPosition(character: Character, with font: UIFont = .systemFont(ofSize: 18.0)) -> CGPoint? {
guard let index = firstIndex(of: character) else {
print("\(character) is missed")
return nil
}
let string = String(self[..<index])
let size = string.size(withAttributes: [.font: font])
return CGPoint(x: size.width, y: 0)
}
}
How to trim first 3 character from a string in swift
You can split your string where separator is a slash, drop the first component and then join it again:
let str = "66/001/0004"
let trimmed = str.split { $0 == "/" }
.dropFirst()
.joined(separator: "/") // "001/0004"
Another option is to find the first slash index and get the substring after it:
if let index = str.firstIndex(of: "/") {
let trimmed = str[str.index(after: index)...] // "001/0004"
// or simply dropping the first character
// let trimmed = str[index...].dropFirst()
}
How can I gave custom Index to String.Index working with unicode in Swift?
You can create an extension on String
where you take the index as either a String.Index
or an Int
, then use that to subscript unicodeScalars
.
extension String {
func unicodeScalarValue(at index: String.Index) -> UInt32 {
unicodeScalars[index].value
}
func unicodeScalarValue(at index: Int) -> UInt32 {
unicodeScalars[self.index(startIndex, offsetBy: index)].value
}
}
"ABC".unicodeScalarValue(at: 0)
"ABC".unicodeScalarValue(at: 1)
"ABC".unicodeScalarValue(at: 2)
Related Topics
Selecting Global or Object Print Function
Difference Between Functions and Closures
Xcode 8/Swift 3: Simple Uipicker Code Not Working
Separating Multiple If Conditions With Commas in Swift
How to Avoid Force Unwrapping a Variable
Knowing Where Retain Cycles Are and Removing Them
Multi-Touch Gesture in Sprite Kit
Swiftui Picker Separate Texts For Selected Item and Selection View
Extensions in My Own Custom Class
Nehotspothelper.Register Not Received Call Back Ios11
Swift 3 How to Display a Confirmation Screen Based on Mfmailcomposeresult Email Screen
Convert a Date (Absolute Time) to Be Sent/Received Across the Network as Data in Swift
What Is the Point of Having Two Different Names For the Same Parameter
Updating Time Text Label Each Minute in Widgetkit
Wrong Specialized Generic Function Gets Called in Swift 3 from an Indirect Call