Least convoluted way of extracting parts of string in Swift 4 [duplicate] - swift

How can I get the nth character of a string? I tried bracket([]) accessor with no luck.
var string = "Hello, world!"
var firstChar = string[0] // Throws error
ERROR: 'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion

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
these two extensions into one. I tried extending StringProtocol
without success, because the index method does not exist there. 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
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 ith 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, so String
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 with NSAttributedString 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.

Swift 5.2
let str = "abcdef"
str[1 ..< 3] // returns "bc"
str[5] // returns "f"
str[80] // returns ""
str.substring(fromIndex: 3) // returns "def"
str.substring(toIndex: str.length - 2) // returns "abcd"
You will need to add this String extension to your project (it's fully tested):
extension String {
var length: Int {
return count
}
subscript (i: Int) -> String {
return self[i ..< i + 1]
}
func substring(fromIndex: Int) -> String {
return self[min(fromIndex, length) ..< length]
}
func substring(toIndex: Int) -> String {
return self[0 ..< max(0, toIndex)]
}
subscript (r: Range<Int>) -> String {
let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
upper: min(length, max(0, r.upperBound))))
let start = index(startIndex, offsetBy: range.lowerBound)
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return String(self[start ..< end])
}
}
Even though Swift always had out of the box solution to this problem (without String extension, which I provided below), I still would strongly recommend using the extension. Why? Because it saved me tens of hours of painful migration from early versions of Swift, where String's syntax was changing almost every release, but all I needed to do was to update the extension's implementation as opposed to refactoring the entire project. Make your choice.
let str = "Hello, world!"
let index = str.index(str.startIndex, offsetBy: 4)
str[index] // returns Character 'o'
let endIndex = str.index(str.endIndex, offsetBy:-2)
str[index ..< endIndex] // returns String "o, worl"
String(str.suffix(from: index)) // returns String "o, world!"
String(str.prefix(upTo: index)) // returns String "Hell"

I just came up with this neat workaround
var firstChar = Array(string)[0]

Xcode 11 β€’ Swift 5.1
You can extend StringProtocol to make the subscript available also to the substrings:
extension StringProtocol {
subscript(_ offset: Int) -> Element { self[index(startIndex, offsetBy: offset)] }
subscript(_ range: Range<Int>) -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
subscript(_ range: ClosedRange<Int>) -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
subscript(_ range: PartialRangeThrough<Int>) -> SubSequence { prefix(range.upperBound.advanced(by: 1)) }
subscript(_ range: PartialRangeUpTo<Int>) -> SubSequence { prefix(range.upperBound) }
subscript(_ range: PartialRangeFrom<Int>) -> SubSequence { suffix(Swift.max(0, count-range.lowerBound)) }
}
extension LosslessStringConvertible {
var string: String { .init(self) }
}
extension BidirectionalCollection {
subscript(safe offset: Int) -> Element? {
guard !isEmpty, let i = index(startIndex, offsetBy: offset, limitedBy: index(before: endIndex)) else { return nil }
return self[i]
}
}
Testing
let test = "Hello USA πŸ‡ΊπŸ‡Έ!!! Hello Brazil πŸ‡§πŸ‡·!!!"
test[safe: 10] // "πŸ‡ΊπŸ‡Έ"
test[11] // "!"
test[10...] // "πŸ‡ΊπŸ‡Έ!!! Hello Brazil πŸ‡§πŸ‡·!!!"
test[10..<12] // "πŸ‡ΊπŸ‡Έ!"
test[10...12] // "πŸ‡ΊπŸ‡Έ!!"
test[...10] // "Hello USA πŸ‡ΊπŸ‡Έ"
test[..<10] // "Hello USA "
test.first // "H"
test.last // "!"
// Subscripting the Substring
test[...][...3] // "Hell"
// Note that they all return a Substring of the original String.
// To create a new String from a substring
test[10...].string // "πŸ‡ΊπŸ‡Έ!!! Hello Brazil πŸ‡§πŸ‡·!!!"

No indexing using integers, only using String.Index. Mostly with linear complexity. You can also create ranges from String.Index and get substrings using them.
Swift 3.0
let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.index(before: someString.endIndex)]
let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)]
let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10)
let substring = someString[range]
Swift 2.x
let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.endIndex.predecessor()]
let charAtIndex = someString[someString.startIndex.advanceBy(10)]
let range = someString.startIndex..<someString.startIndex.advanceBy(10)
let subtring = someString[range]
Note that you can't ever use an index (or range) created from one string to another string
let index10 = someString.startIndex.advanceBy(10)
//will compile
//sometimes it will work but sometimes it will crash or result in undefined behaviour
let charFromAnotherString = anotherString[index10]

Swift 4
let str = "My String"
String at index
let index = str.index(str.startIndex, offsetBy: 3)
String(str[index]) // "S"
Substring
let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)
String(str[startIndex...endIndex]) // "Strin"
First n chars
let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[..<startIndex]) // "My "
Last n chars
let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[startIndex...]) // "String"
Swift 2 and 3
str = "My String"
**String At Index **
Swift 2
let charAtIndex = String(str[str.startIndex.advancedBy(3)]) // charAtIndex = "S"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)]
SubString fromIndex toIndex
Swift 2
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)] // subStr = "Strin"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)...str.index(str.startIndex, offsetBy: 7)]
First n chars
let first2Chars = String(str.characters.prefix(2)) // first2Chars = "My"
Last n chars
let last3Chars = String(str.characters.suffix(3)) // last3Chars = "ing"

Swift 5.3
I think this is very elegant. Kudos at Paul Hudson of "Hacking with Swift" for this solution:
#available (macOS 10.15, * )
extension String {
subscript(idx: Int) -> String {
String(self[index(startIndex, offsetBy: idx)])
}
}
Then to get one character out of the String you simply do:
var string = "Hello, world!"
var firstChar = string[0] // No error, returns "H" as a String
NB: I just wanted to add, this will return a String as pointed out in the comments. I think it might be unexpected for Swift users, but often I need a String to use in my code straight away and not a Character type, so it does simplify my code a little bit avoiding a conversion from Character to String later.

Swift 2.0 as of Xcode 7 GM Seed
var text = "Hello, world!"
let firstChar = text[text.startIndex.advancedBy(0)] // "H"
For the nth character, replace 0 with n-1.
Edit: Swift 3.0
text[text.index(text.startIndex, offsetBy: 0)]
n.b. there are simpler ways of grabbing certain characters in the string
e.g. let firstChar = text.characters.first

If you see Cannot subscript a value of type 'String'... use this extension:
Swift 3
extension String {
subscript (i: Int) -> Character {
return self[self.characters.index(self.startIndex, offsetBy: i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return self[start..<end]
}
subscript (r: ClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return self[start...end]
}
}
Swift 2.3
extension String {
subscript(integerIndex: Int) -> Character {
let index = advance(startIndex, integerIndex)
return self[index]
}
subscript(integerRange: Range<Int>) -> String {
let start = advance(startIndex, integerRange.startIndex)
let end = advance(startIndex, integerRange.endIndex)
let range = start..<end
return self[range]
}
}
Source: http://oleb.net/blog/2014/07/swift-strings/

Swift 2.2 Solution:
The following extension works in Xcode 7, this is a combination of this solution and Swift 2.0 syntax conversion.
extension String {
subscript(integerIndex: Int) -> Character {
let index = startIndex.advancedBy(integerIndex)
return self[index]
}
subscript(integerRange: Range<Int>) -> String {
let start = startIndex.advancedBy(integerRange.startIndex)
let end = startIndex.advancedBy(integerRange.endIndex)
let range = start..<end
return self[range]
}
}

The swift string class does not provide the ability to get a character at a specific index because of its native support for UTF characters. The variable length of a UTF character in memory makes jumping directly to a character impossible. That means you have to manually loop over the string each time.
You can extend String to provide a method that will loop through the characters until your desired index
extension String {
func characterAtIndex(index: Int) -> Character? {
var cur = 0
for char in self {
if cur == index {
return char
}
cur++
}
return nil
}
}
myString.characterAtIndex(0)!

You can do it by convert String into Array and get it by specific index using subscript as below
var str = "Hello"
let s = Array(str)[2]
print(s)

As an aside note, there are a few functions applyable directly to the Character-chain representation of a String, like this:
var string = "Hello, playground"
let firstCharacter = string.characters.first // returns "H"
let lastCharacter = string.characters.last // returns "d"
The result is of type Character, but you can cast it to a String.
Or this:
let reversedString = String(string.characters.reverse())
// returns "dnuorgyalp ,olleH"
:-)

Swift 4
String(Array(stringToIndex)[index])
This is probably the best way of solving this problem one-time. You probably want to cast the String as an array first, and then cast the result as a String again. Otherwise, a Character will be returned instead of a String.
Example String(Array("HelloThere")[1]) will return "e" as a String.
(Array("HelloThere")[1] will return "e" as a Character.
Swift does not allow Strings to be indexed like arrays, but this gets the job done, brute-force style.

My very simple solution:
Swift 4.1:
let myString = "Test string"
let index = 0
let firstCharacter = myString[String.Index(encodedOffset: index)]
Swift 5.1:
let firstCharacter = myString[String.Index.init(utf16Offset: index, in: myString)]

I just had the same issue. Simply do this:
var aString: String = "test"
var aChar:unichar = (aString as NSString).characterAtIndex(0)

In Swift 5 without extension to the String :
var str = "ABCDEFGH"
for char in str {
if(char == "C") { }
}
Above Swift code as same as that Java code :
int n = 8;
var str = "ABCDEFGH"
for (int i=0; i<n; i++) {
if (str.charAt(i) == 'C') { }
}

My solution is in one line, supposing cadena is the string and 4 is the nth position that you want:
let character = cadena[advance(cadena.startIndex, 4)]
Simple... I suppose Swift will include more things about substrings in future versions.

Swift3
You can use subscript syntax to access the Character at a particular String index.
let greeting = "Guten Tag!"
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index] // a
Visit https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
or we can do a String Extension in Swift 4
extension String {
func getCharAtIndex(_ index: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: index)]
}
}
USAGE:
let foo = "ABC123"
foo.getCharAtIndex(2) //C

By now, subscript(_:) is unavailable. As well as we can't do this
str[0]
with string.We have to provide "String.Index"
But, how can we give our own index number in this way, instead we can use,
string[str.index(str.startIndex, offsetBy: 0)]

Swift 4.2 or later
Range and partial range subscripting using String's indices property
As variation of #LeoDabus nice answer, we may add an additional extension to DefaultIndices with the purpose of allowing us to fall back on the indices property of String when implementing the custom subscripts (by Int specialized ranges and partial ranges) for the latter.
extension DefaultIndices {
subscript(at: Int) -> Elements.Index { index(startIndex, offsetBy: at) }
}
// Moving the index(_:offsetBy:) to an extension yields slightly
// briefer implementations for these String extensions.
extension String {
subscript(range: Range<Int>) -> SubSequence {
let start = indices[range.lowerBound]
return self[start..<indices[start...][range.count]]
}
subscript(range: ClosedRange<Int>) -> SubSequence {
let start = indices[range.lowerBound]
return self[start...indices[start...][range.count]]
}
subscript(range: PartialRangeFrom<Int>) -> SubSequence {
self[indices[range.lowerBound]...]
}
subscript(range: PartialRangeThrough<Int>) -> SubSequence {
self[...indices[range.upperBound]]
}
subscript(range: PartialRangeUpTo<Int>) -> SubSequence {
self[..<indices[range.upperBound]]
}
}
let str = "foo bar baz bax"
print(str[4..<6]) // "ba"
print(str[4...6]) // "bar"
print(str[4...]) // "bar baz bax"
print(str[...6]) // "foo bar"
print(str[..<6]) // "foo ba"
Thanks #LeoDabus for the pointing me in the direction of using the indices property as an(other) alternative to String subscripting!

Swift 5.1.3:
Add a String extension:
extension String {
func stringAt(_ i: Int) -> String {
return String(Array(self)[i])
}
func charAt(_ i: Int) -> Character {
return Array(self)[i]
}
}
let str = "Teja Kumar"
let str1: String = str.stringAt(2) //"j"
let str2: Character = str.charAt(5) //"k"

We have subscript which will very useful here
But String subscript will take param as String.Index so most of the people gets confuse here how to pass String.Index to get details how to form String.Index as per our requirement please look at below documentation Apple Documentation
Here i have created one extension method to get nth character in string
extension String {
subscript(i: Int) -> String {
return i < count ? String(self[index(startIndex, offsetBy: i)]) : ""
}
}
Usage
let name = "Narayana Rao"
print(name[11]) //o
print(name[1]) //a
print(name[0]) //N
print(name[30]) //""
if you pass index which is out of bounds of String count it will return empty String

Swift 3: another solution (tested in playground)
extension String {
func substr(_ start:Int, length:Int=0) -> String? {
guard start > -1 else {
return nil
}
let count = self.characters.count - 1
guard start <= count else {
return nil
}
let startOffset = max(0, start)
let endOffset = length > 0 ? min(count, startOffset + length - 1) : count
return self[self.index(self.startIndex, offsetBy: startOffset)...self.index(self.startIndex, offsetBy: endOffset)]
}
}
Usage:
let txt = "12345"
txt.substr(-1) //nil
txt.substr(0) //"12345"
txt.substr(0, length: 0) //"12345"
txt.substr(1) //"2345"
txt.substr(2) //"345"
txt.substr(3) //"45"
txt.substr(4) //"5"
txt.substr(6) //nil
txt.substr(0, length: 1) //"1"
txt.substr(1, length: 1) //"2"
txt.substr(2, length: 1) //"3"
txt.substr(3, length: 1) //"4"
txt.substr(3, length: 2) //"45"
txt.substr(3, length: 3) //"45"
txt.substr(4, length: 1) //"5"
txt.substr(4, length: 2) //"5"
txt.substr(5, length: 1) //nil
txt.substr(5, length: -1) //nil
txt.substr(-1, length: -1) //nil

Best way which worked for me is:
var firstName = "Olivia"
var lastName = "Pope"
var nameInitials.text = "\(firstName.prefix(1))" + "\ (lastName.prefix(1))"
Output:"OP"

Update for swift 2.0 subString
public extension String {
public subscript (i: Int) -> String {
return self.substringWithRange(self.startIndex..<self.startIndex.advancedBy(i + 1))
}
public subscript (r: Range<Int>) -> String {
get {
return self.substringWithRange(self.startIndex.advancedBy(r.startIndex)..<self.startIndex.advancedBy(r.endIndex))
}
}
}

I think that a fast answer for get the first character could be:
let firstCharacter = aString[aString.startIndex]
It's so much elegant and performance than:
let firstCharacter = Array(aString.characters).first
But.. if you want manipulate and do more operations with strings you could think create an extension..here is one extension with this approach, it's quite similar to that already posted here:
extension String {
var length : Int {
return self.characters.count
}
subscript(integerIndex: Int) -> Character {
let index = startIndex.advancedBy(integerIndex)
return self[index]
}
subscript(integerRange: Range<Int>) -> String {
let start = startIndex.advancedBy(integerRange.startIndex)
let end = startIndex.advancedBy(integerRange.endIndex)
let range = start..<end
return self[range]
}
}
BUT IT'S A TERRIBLE IDEA!!
The extension below is horribly inefficient. Every time a string is accessed with an integer, an O(n) function to advance its starting index is run. Running a linear loop inside another linear loop means this for loop is accidentally O(n2) β€” as the length of the string increases, the time this loop takes increases quadratically.
Instead of doing that you could use the characters's string collection.

Swift 3
extension String {
public func charAt(_ i: Int) -> Character {
return self[self.characters.index(self.startIndex, offsetBy: i)]
}
public subscript (i: Int) -> String {
return String(self.charAt(i) as Character)
}
public subscript (r: Range<Int>) -> String {
return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
}
public subscript (r: CountableClosedRange<Int>) -> String {
return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
}
}
Usage
let str = "Hello World"
let sub = str[0...4]
Helpful Programming Tips and Tricks (written by me)

Here's an extension you can use, working with Swift 3.1. A single index will return a Character, which seems intuitive when indexing a String, and a Range will return a String.
extension String {
subscript (i: Int) -> Character {
return Array(self.characters)[i]
}
subscript (r: CountableClosedRange<Int>) -> String {
return String(Array(self.characters)[r])
}
subscript (r: CountableRange<Int>) -> String {
return self[r.lowerBound...r.upperBound-1]
}
}
Some examples of the extension in action:
let string = "Hello"
let c1 = string[1] // Character "e"
let c2 = string[-1] // fatal error: Index out of range
let r1 = string[1..<4] // String "ell"
let r2 = string[1...4] // String "ello"
let r3 = string[1...5] // fatal error: Array index is out of range
n.b. You could add an additional method to the above extension to return a String with a single character if wanted:
subscript (i: Int) -> String {
return String(self[i])
}
Note that then you would have to explicitly specify the type you wanted when indexing the string:
let c: Character = string[3] // Character "l"
let s: String = string[0] // String "H"

Get & Set Subscript (String & Substring) - Swift 4.2
Swift 4.2, Xcode 10
I based my answer off of #alecarlson's answer.
The only big difference is you can get a Substring or a String returned (and in some cases, a single Character). You can also get and set the subscript.
Lastly, mine is a bit more cumbersome and longer than #alecarlson's answer and as such, I suggest you put it in a source file.
Extension:
public extension String {
public subscript (i: Int) -> Character {
get {
return self[index(startIndex, offsetBy: i)]
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> String {
get {
return "\(self[index(startIndex, offsetBy: i)])"
}
set (c) {
let n = index(startIndex, offsetBy: i)
self.replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ..< end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ... end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ..< end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> Substring {
get {
return Substring("\(self[index(startIndex, offsetBy: i)])")
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
}
public extension Substring {
public subscript (i: Int) -> Character {
get {
return self[index(startIndex, offsetBy: i)]
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> String {
get {
return "\(self[index(startIndex, offsetBy: i)])"
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ..< end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ... end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ..< end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> Substring {
get {
return Substring("\(self[index(startIndex, offsetBy: i)])")
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
}

Related

substring(with:)' is deprecated: Please use String slicing subscript [duplicate]

I have the following simple code written in Swift 3:
let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)
From Xcode 9 beta 5, I get the following warning:
'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator.
How can this slicing subscript with partial range from be used in Swift 4?
You should leave one side empty, hence the name "partial range".
let newStr = str[..<index]
The same stands for partial range from operators, just leave the other side empty:
let newStr = str[index...]
Keep in mind that these range operators return a Substring. If you want to convert it to a string, use String's initialization function:
let newStr = String(str[..<index])
You can read more about the new substrings here.
Convert Substring (Swift 3) to String Slicing (Swift 4)
Examples In Swift 3, 4:
let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4
let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4
let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range]) // Swift 4
Swift 5, 4
Usage
let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor
Code
import Foundation
public extension String {
subscript(value: Int) -> Character {
self[index(at: value)]
}
}
public extension String {
subscript(value: NSRange) -> Substring {
self[value.lowerBound..<value.upperBound]
}
}
public extension String {
subscript(value: CountableClosedRange<Int>) -> Substring {
self[index(at: value.lowerBound)...index(at: value.upperBound)]
}
subscript(value: CountableRange<Int>) -> Substring {
self[index(at: value.lowerBound)..<index(at: value.upperBound)]
}
subscript(value: PartialRangeUpTo<Int>) -> Substring {
self[..<index(at: value.upperBound)]
}
subscript(value: PartialRangeThrough<Int>) -> Substring {
self[...index(at: value.upperBound)]
}
subscript(value: PartialRangeFrom<Int>) -> Substring {
self[index(at: value.lowerBound)...]
}
}
private extension String {
func index(at offset: Int) -> String.Index {
index(startIndex, offsetBy: offset)
}
}
Shorter in Swift 4/5:
let string = "123456"
let firstThree = String(string.prefix(3)) //"123"
let lastThree = String(string.suffix(3)) //"456"
Swift5
(Java's substring method):
extension String {
func subString(from: Int, to: Int) -> String {
let startIndex = self.index(self.startIndex, offsetBy: from)
let endIndex = self.index(self.startIndex, offsetBy: to)
return String(self[startIndex..<endIndex])
}
}
Usage:
var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels
The conversion of your code to Swift 4 can also be done this way:
let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)
You can use the code below to have a new string:
let newString = String(str.prefix(upTo: index))
substring(from: index) Converted to [index...]
Check the sample
let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)
text.substring(from: index) // "4567890" [Swift 3]
String(text[index...]) // "4567890" [Swift 4]
Some useful extensions:
extension String {
func substring(from: Int, to: Int) -> String {
let start = index(startIndex, offsetBy: from)
let end = index(start, offsetBy: to - from)
return String(self[start ..< end])
}
func substring(range: NSRange) -> String {
return substring(from: range.lowerBound, to: range.upperBound)
}
}
Example of uppercasedFirstCharacter convenience property in Swift3 and Swift4.
Property uppercasedFirstCharacterNew demonstrates how to use String slicing subscript in Swift4.
extension String {
public var uppercasedFirstCharacterOld: String {
if characters.count > 0 {
let splitIndex = index(after: startIndex)
let firstCharacter = substring(to: splitIndex).uppercased()
let sentence = substring(from: splitIndex)
return firstCharacter + sentence
} else {
return self
}
}
public var uppercasedFirstCharacterNew: String {
if characters.count > 0 {
let splitIndex = index(after: startIndex)
let firstCharacter = self[..<splitIndex].uppercased()
let sentence = self[splitIndex...]
return firstCharacter + sentence
} else {
return self
}
}
}
let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"
let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"
You can create your custom subString method using extension to class String as below:
extension String {
func subString(startIndex: Int, endIndex: Int) -> String {
let end = (endIndex - self.count) + 1
let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
let indexEndOfText = self.index(self.endIndex, offsetBy: end)
let substring = self[indexStartOfText..<indexEndOfText]
return String(substring)
}
}
Creating SubString (prefix and suffix) from String using Swift 4:
let str : String = "ilike"
for i in 0...str.count {
let index = str.index(str.startIndex, offsetBy: i) // String.Index
let prefix = str[..<index] // String.SubSequence
let suffix = str[index...] // String.SubSequence
print("prefix \(prefix), suffix : \(suffix)")
}
Output
prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix :
If you want to generate a substring between 2 indices , use :
let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex
I have written a string extension for replacement of 'String: subString:'
extension String {
func sliceByCharacter(from: Character, to: Character) -> String? {
let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
return String(self[fromIndex...toIndex])
}
func sliceByString(from:String, to:String) -> String? {
//From - startIndex
var range = self.range(of: from)
let subString = String(self[range!.upperBound...])
//To - endIndex
range = subString.range(of: to)
return String(subString[..<range!.lowerBound])
}
}
Usage : "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")
Example Result : "1511508780012"
PS: Optionals are forced to unwrap. Please add Type safety check wherever necessary.
If you are trying to just get a substring up to a specific character, you don't need to find the index first, you can just use the prefix(while:) method
let str = "Hello, playground"
let subString = str.prefix { $0 != "," } // "Hello" as a String.SubSequence
When programming I often have strings with just plain A-Za-z and 0-9. No need for difficult Index actions. This extension is based on the plain old left / mid / right functions.
extension String {
// LEFT
// Returns the specified number of chars from the left of the string
// let str = "Hello"
// print(str.left(3)) // Hel
func left(_ to: Int) -> String {
return "\(self[..<self.index(startIndex, offsetBy: to)])"
}
// RIGHT
// Returns the specified number of chars from the right of the string
// let str = "Hello"
// print(str.left(3)) // llo
func right(_ from: Int) -> String {
return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
}
// MID
// Returns the specified number of chars from the startpoint of the string
// let str = "Hello"
// print(str.left(2,amount: 2)) // ll
func mid(_ from: Int, amount: Int) -> String {
let x = "\(self[self.index(startIndex, offsetBy: from)...])"
return x.left(amount)
}
}
Hope this will help little more :-
var string = "123456789"
If you want a substring after some particular index.
var indexStart = string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart = String (string[indexStart...])//23456789
If you want a substring after removing some string at the end.
var indexEnd = string.index(before: string.endIndex)
var strIndexEnd = String (string[..<indexEnd])//12345678
you can also create indexes with the following code :-
var indexWithOffset = string.index(string.startIndex, offsetBy: 4)
with this method you can get specific range of string.you need to pass start index and after that total number of characters you want.
extension String{
func substring(fromIndex : Int,count : Int) -> String{
let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
let range = startIndex..<endIndex
return String(self[range])
}
}
This is my solution, no warning, no errors, but perfect
let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))
You can try in this way and will get proper results.
the simples way that I use is :
String(Array(str)[2...4])
Swift 4, 5, 5+
Substring from Last
let str = "Hello World"
let removeFirstSix = String(str.dropFirst(6))
print(removeFirstSix) //World
Substring from First
let removeLastSix = String(str.dropLast(6))
print(removeLastSix) //Hello
Hope it would be helpful.
extension String {
func getSubString(_ char: Character) -> String {
var subString = ""
for eachChar in self {
if eachChar == char {
return subString
} else {
subString += String(eachChar)
}
}
return subString
}
}
let str: String = "Hello, playground"
print(str.getSubString(","))

How to extract chosen character from string in swift [Archived]

I don't know how to extract a character, a word from a string in SWIFT.
I'd appreciate if someone could answer my question.
var Sth:String = "ABCDEF"
How do I extract only A or B or C
Edited 2/22/2021: I appreciate all of the answer, please do not attempt answering this further
Try this:
extension String {
func index(from: Int) -> Index {
return self.index(startIndex, offsetBy: from)
}
func substringtx(with r: Range<Int>) -> String {
let startIndex = index(from: r.lowerBound)
let endIndex = index(from: r.upperBound)
return substring(with: startIndex..<endIndex)
}
}
Example:
var str:String = "ABCDEF"
print(str.substringtx(with: 0..<1)) //prints 'A'
print(str.substringtx(with: 1..<2)) //prints 'B'

How can I use String substring in Swift 4? 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator

I have the following simple code written in Swift 3:
let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)
From Xcode 9 beta 5, I get the following warning:
'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator.
How can this slicing subscript with partial range from be used in Swift 4?
You should leave one side empty, hence the name "partial range".
let newStr = str[..<index]
The same stands for partial range from operators, just leave the other side empty:
let newStr = str[index...]
Keep in mind that these range operators return a Substring. If you want to convert it to a string, use String's initialization function:
let newStr = String(str[..<index])
You can read more about the new substrings here.
Convert Substring (Swift 3) to String Slicing (Swift 4)
Examples In Swift 3, 4:
let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4
let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4
let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range]) // Swift 4
Swift 5, 4
Usage
let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor
Code
import Foundation
public extension String {
subscript(value: Int) -> Character {
self[index(at: value)]
}
}
public extension String {
subscript(value: NSRange) -> Substring {
self[value.lowerBound..<value.upperBound]
}
}
public extension String {
subscript(value: CountableClosedRange<Int>) -> Substring {
self[index(at: value.lowerBound)...index(at: value.upperBound)]
}
subscript(value: CountableRange<Int>) -> Substring {
self[index(at: value.lowerBound)..<index(at: value.upperBound)]
}
subscript(value: PartialRangeUpTo<Int>) -> Substring {
self[..<index(at: value.upperBound)]
}
subscript(value: PartialRangeThrough<Int>) -> Substring {
self[...index(at: value.upperBound)]
}
subscript(value: PartialRangeFrom<Int>) -> Substring {
self[index(at: value.lowerBound)...]
}
}
private extension String {
func index(at offset: Int) -> String.Index {
index(startIndex, offsetBy: offset)
}
}
Shorter in Swift 4/5:
let string = "123456"
let firstThree = String(string.prefix(3)) //"123"
let lastThree = String(string.suffix(3)) //"456"
Swift5
(Java's substring method):
extension String {
func subString(from: Int, to: Int) -> String {
let startIndex = self.index(self.startIndex, offsetBy: from)
let endIndex = self.index(self.startIndex, offsetBy: to)
return String(self[startIndex..<endIndex])
}
}
Usage:
var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels
The conversion of your code to Swift 4 can also be done this way:
let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)
You can use the code below to have a new string:
let newString = String(str.prefix(upTo: index))
substring(from: index) Converted to [index...]
Check the sample
let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)
text.substring(from: index) // "4567890" [Swift 3]
String(text[index...]) // "4567890" [Swift 4]
Some useful extensions:
extension String {
func substring(from: Int, to: Int) -> String {
let start = index(startIndex, offsetBy: from)
let end = index(start, offsetBy: to - from)
return String(self[start ..< end])
}
func substring(range: NSRange) -> String {
return substring(from: range.lowerBound, to: range.upperBound)
}
}
Example of uppercasedFirstCharacter convenience property in Swift3 and Swift4.
Property uppercasedFirstCharacterNew demonstrates how to use String slicing subscript in Swift4.
extension String {
public var uppercasedFirstCharacterOld: String {
if characters.count > 0 {
let splitIndex = index(after: startIndex)
let firstCharacter = substring(to: splitIndex).uppercased()
let sentence = substring(from: splitIndex)
return firstCharacter + sentence
} else {
return self
}
}
public var uppercasedFirstCharacterNew: String {
if characters.count > 0 {
let splitIndex = index(after: startIndex)
let firstCharacter = self[..<splitIndex].uppercased()
let sentence = self[splitIndex...]
return firstCharacter + sentence
} else {
return self
}
}
}
let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"
let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"
You can create your custom subString method using extension to class String as below:
extension String {
func subString(startIndex: Int, endIndex: Int) -> String {
let end = (endIndex - self.count) + 1
let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
let indexEndOfText = self.index(self.endIndex, offsetBy: end)
let substring = self[indexStartOfText..<indexEndOfText]
return String(substring)
}
}
Creating SubString (prefix and suffix) from String using Swift 4:
let str : String = "ilike"
for i in 0...str.count {
let index = str.index(str.startIndex, offsetBy: i) // String.Index
let prefix = str[..<index] // String.SubSequence
let suffix = str[index...] // String.SubSequence
print("prefix \(prefix), suffix : \(suffix)")
}
Output
prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix :
If you want to generate a substring between 2 indices , use :
let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex
I have written a string extension for replacement of 'String: subString:'
extension String {
func sliceByCharacter(from: Character, to: Character) -> String? {
let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
return String(self[fromIndex...toIndex])
}
func sliceByString(from:String, to:String) -> String? {
//From - startIndex
var range = self.range(of: from)
let subString = String(self[range!.upperBound...])
//To - endIndex
range = subString.range(of: to)
return String(subString[..<range!.lowerBound])
}
}
Usage : "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")
Example Result : "1511508780012"
PS: Optionals are forced to unwrap. Please add Type safety check wherever necessary.
If you are trying to just get a substring up to a specific character, you don't need to find the index first, you can just use the prefix(while:) method
let str = "Hello, playground"
let subString = str.prefix { $0 != "," } // "Hello" as a String.SubSequence
When programming I often have strings with just plain A-Za-z and 0-9. No need for difficult Index actions. This extension is based on the plain old left / mid / right functions.
extension String {
// LEFT
// Returns the specified number of chars from the left of the string
// let str = "Hello"
// print(str.left(3)) // Hel
func left(_ to: Int) -> String {
return "\(self[..<self.index(startIndex, offsetBy: to)])"
}
// RIGHT
// Returns the specified number of chars from the right of the string
// let str = "Hello"
// print(str.left(3)) // llo
func right(_ from: Int) -> String {
return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
}
// MID
// Returns the specified number of chars from the startpoint of the string
// let str = "Hello"
// print(str.left(2,amount: 2)) // ll
func mid(_ from: Int, amount: Int) -> String {
let x = "\(self[self.index(startIndex, offsetBy: from)...])"
return x.left(amount)
}
}
Hope this will help little more :-
var string = "123456789"
If you want a substring after some particular index.
var indexStart = string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart = String (string[indexStart...])//23456789
If you want a substring after removing some string at the end.
var indexEnd = string.index(before: string.endIndex)
var strIndexEnd = String (string[..<indexEnd])//12345678
you can also create indexes with the following code :-
var indexWithOffset = string.index(string.startIndex, offsetBy: 4)
with this method you can get specific range of string.you need to pass start index and after that total number of characters you want.
extension String{
func substring(fromIndex : Int,count : Int) -> String{
let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
let range = startIndex..<endIndex
return String(self[range])
}
}
This is my solution, no warning, no errors, but perfect
let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))
You can try in this way and will get proper results.
the simples way that I use is :
String(Array(str)[2...4])
Swift 4, 5, 5+
Substring from Last
let str = "Hello World"
let removeFirstSix = String(str.dropFirst(6))
print(removeFirstSix) //World
Substring from First
let removeLastSix = String(str.dropLast(6))
print(removeLastSix) //Hello
Hope it would be helpful.
extension String {
func getSubString(_ char: Character) -> String {
var subString = ""
for eachChar in self {
if eachChar == char {
return subString
} else {
subString += String(eachChar)
}
}
return subString
}
}
let str: String = "Hello, playground"
print(str.getSubString(","))

In Swift, how to modify a character in string with subscript?

Like in C, we can simply do
str[i] = str[j]
But how to write the similar logic in swift?
Here is my code, but got error:
Cannot assign through subscript: subscript is get-only
let indexI = targetString.index(targetString.startIndex, offsetBy: i)
let indexJ = targetString.index(targetString.startIndex, offsetBy: j)
targetString[indexI] = targetString[indexJ]
I know it may work by using this method, but it's too inconvenient
replaceSubrange(, with: )
In C, a string (char *) can be treated as an array of characters. In Swift, you can convert the String to an [Character], do the modifications you want, and then convert the [Character] back to String.
For example:
let str = "hello"
var strchars = Array(str)
strchars[0] = strchars[4]
let str2 = String(strchars)
print(str2) // "oello"
This might seem like a lot of work for a single modification, but if you are moving many characters this way, you only have to convert once each direction.
Reverse a String
Here's an example of a simple algorithm to reverse a string. By converting to an array of characters first, this algorithm is similar to the way you might do it in C:
let str = "abcdefg"
var strchars = Array(str)
var start = 0
var end = strchars.count - 1
while start < end {
let temp = strchars[start]
strchars[start] = strchars[end]
strchars[end] = temp
start += 1
end -= 1
}
let str2 = String(strchars)
print(str2) // "gfedcba"
Dealing with String with Swift is major pain in the a**. Unlike most languages I know that treat string as an array of characters, Swift treats strings as collection of extended grapheme clusters and the APIs to access them is really clumsy. Changes are coming in Swift 4 but that manifesto lost me about 10 paragraphs in.
Back to your question... you can replace the character like this:
var targetString = "Hello world"
let i = 0
let j = 1
let indexI = targetString.index(targetString.startIndex, offsetBy: i)
let indexJ = targetString.index(targetString.startIndex, offsetBy: j)
targetString.replaceSubrange(indexI...indexI, with: targetString[indexJ...indexJ])
print(targetString) // eello world
I was quite shocked as well by the fact that swift makes string indexing so damn complicated. For that reason, I have built some string extensions that enable you to retrieve and change parts of strings based on indices, closed ranges, and open ranges, PartialRangeFrom, PartialRangeThrough, and PartialRangeUpTo. You can download the repository I created here
You can also pass in negative numbers in order to access characters from the end backwards.
public extension String {
/**
Enables passing in negative indices to access characters
starting from the end and going backwards.
if num is negative, then it is added to the
length of the string to retrieve the true index.
*/
func negativeIndex(_ num: Int) -> Int {
return num < 0 ? num + self.count : num
}
func strOpenRange(index i: Int) -> Range<String.Index> {
let j = negativeIndex(i)
return strOpenRange(j..<(j + 1), checkNegative: false)
}
func strOpenRange(
_ range: Range<Int>, checkNegative: Bool = true
) -> Range<String.Index> {
var lower = range.lowerBound
var upper = range.upperBound
if checkNegative {
lower = negativeIndex(lower)
upper = negativeIndex(upper)
}
let idx1 = index(self.startIndex, offsetBy: lower)
let idx2 = index(self.startIndex, offsetBy: upper)
return idx1..<idx2
}
func strClosedRange(
_ range: CountableClosedRange<Int>, checkNegative: Bool = true
) -> ClosedRange<String.Index> {
var lower = range.lowerBound
var upper = range.upperBound
if checkNegative {
lower = negativeIndex(lower)
upper = negativeIndex(upper)
}
let start = self.index(self.startIndex, offsetBy: lower)
let end = self.index(start, offsetBy: upper - lower)
return start...end
}
// MARK: - Subscripts
/**
Gets and sets a character at a given index.
Negative indices are added to the length so that
characters can be accessed from the end backwards
Usage: `string[n]`
*/
subscript(_ i: Int) -> String {
get {
return String(self[strOpenRange(index: i)])
}
set {
let range = strOpenRange(index: i)
replaceSubrange(range, with: newValue)
}
}
/**
Gets and sets characters in an open range.
Supports negative indexing.
Usage: `string[n..<n]`
*/
subscript(_ r: Range<Int>) -> String {
get {
return String(self[strOpenRange(r)])
}
set {
replaceSubrange(strOpenRange(r), with: newValue)
}
}
/**
Gets and sets characters in a closed range.
Supports negative indexing
Usage: `string[n...n]`
*/
subscript(_ r: CountableClosedRange<Int>) -> String {
get {
return String(self[strClosedRange(r)])
}
set {
replaceSubrange(strClosedRange(r), with: newValue)
}
}
/// `string[n...]`. See PartialRangeFrom
subscript(r: PartialRangeFrom<Int>) -> String {
get {
return String(self[strOpenRange(r.lowerBound..<self.count)])
}
set {
replaceSubrange(strOpenRange(r.lowerBound..<self.count), with: newValue)
}
}
/// `string[...n]`. See PartialRangeThrough
subscript(r: PartialRangeThrough<Int>) -> String {
get {
let upper = negativeIndex(r.upperBound)
return String(self[strClosedRange(0...upper, checkNegative: false)])
}
set {
let upper = negativeIndex(r.upperBound)
replaceSubrange(
strClosedRange(0...upper, checkNegative: false), with: newValue
)
}
}
/// `string[...<n]`. See PartialRangeUpTo
subscript(r: PartialRangeUpTo<Int>) -> String {
get {
let upper = negativeIndex(r.upperBound)
return String(self[strOpenRange(0..<upper, checkNegative: false)])
}
set {
let upper = negativeIndex(r.upperBound)
replaceSubrange(
strOpenRange(0..<upper, checkNegative: false), with: newValue
)
}
}
}
Usage:
let text = "012345"
print(text[2]) // "2"
print(text[-1] // "5"
print(text[1...3]) // "123"
print(text[2..<3]) // "2"
print(text[3...]) // "345"
print(text[...3]) // "0123"
print(text[..<3]) // "012"
print(text[(-3)...] // "345"
print(text[...(-2)] // "01234"
All of the above works with assignment as well. All subscripts have getters and setters.
a new extension added,
since String conforms to BidirectionalCollection Protocol
extension String{
subscript(at i: Int) -> String? {
get {
if i < count{
let idx = index(startIndex, offsetBy: i)
return String(self[idx])
}
else{
return nil
}
}
set {
if i < count{
let idx = index(startIndex, offsetBy: i)
remove(at: idx)
if let new = newValue, let first = new.first{
insert(first, at: idx)
}
}
}
}
}
call like this:
var str = "fighter"
str[at: 2] = "6"

Print one element of a Set in Swift

I have a set like this:
var someItems: Set = [7,3,8]
And I want to print out only the the number 7 of the set above.
How can I do this?
As per the given problem, we can just print like this
Swift 3.0
print(someItems.first!)
or
print(someItems[someItems.startIndex])
As #Hamish pointed out that set is an unordered collection and is not guaranteed to print out the first element which really makes sense, so in order to get 7, we can have a foreach loop
for (index,item) in someItems.enumerated() {
if item == 7 {
print("\(item) found at index = \(index)")
}
}
Another way of checking
if someItems.contains(7) {
print("7 is there")
}
You can use this extension to refer to the set member by index, so someItems[0] for example.
extension Set {
var length: Int {
return count
}
subscript (i: Int) -> Set {
return self[i ..< i + 1]
}
func substring(fromIndex: Int) -> Set {
return self[Swift.min(fromIndex, length) ..< length]
}
func substring(toIndex: Int) -> Set {
return self[0 ..< Swift.max(0, toIndex)]
}
subscript (r: Range<Int>) -> Set {
let range = Range(uncheckedBounds: (lower: Swift.max(0, Swift.min(length, r.lowerBound)),
upper: Swift.min(length, Swift.max(0, r.upperBound))))
let start = index(startIndex, offsetBy: range.lowerBound)
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return Set(self[start ..< end])
}
}