It used to be you could use substring to get a portion of a string. That has been deprecated in favor on string index. But I can't seem to make a string index out of integers.
var str = "hellooo"
let newindex = str.index(after: 3)
str = str[newindex...str.endIndex]
No matter what the string is, I want the second 3 characters. So and str would contain "loo". How can I do this?
Drop the first three characters and the get the remaining first three characters
let str = "helloo"
let secondThreeCharacters = String(str.dropFirst(3).prefix(3))
You might add some code to handle the case if there are less than 6 characters in the string
Related
I fail to understand the problem Xcode is confronting me with in this line:
iteration.template = template[iterationSubstring.endIndex...substring.startIndex]
template is a String and iterationSubstring and substring are Substrings of template. Xcode highlights the opening square bracket with the following message:
Subscript 'subscript(_:)' requires the types 'Substring.Index' and 'Int' be equivalent
The error message does not make any sense to me. I try to obtain a Substring by creating a Range<String.Index> with the [template.startIndex...template.endIndex] subscript. How is this related to Int? And why does the same pattern work elsewhere?
Xcode playground code reproducing the problem:
import Foundation
let template = "This is an ordinary string literal."
let firstSubstringStart = template.index(template.startIndex, offsetBy: 5)
let firstSubstringEnd = template.index(template.startIndex, offsetBy: 7)
let firstSubstring = template[firstSubstringStart...firstSubstringEnd]
let secondSubstringStart = template.index(template.startIndex, offsetBy: 10)
let secondSubstringEnd = template.index(template.startIndex, offsetBy: 12)
let secondSubstring = template[secondSubstringStart...secondSubstringEnd]
let part: String = template[firstSubstring.endIndex...secondSubstring.startIndex]
After all I have a template string and two substrings of it. I want to get a String ranging from the end of the first Substring to the start of the second Substring.
The current version of Swift works with the Substring struct which is a sliced String.
The error seems to be misleading and occurs if you are going to assign a (range-subscripted) Substring to a String variable.
To fix the error create a String from the Substring
iteration.template = String(template[iterationSubstring.endIndex...substring.startIndex])
Nevertheless you are strongly discouraged from creating ranges with indices from different strings (iterationSubstring and substring). Slice the main string, the indices are preserved.
The crash in the second (meanwhile deleted) example occurred because the last character of a string is at index before endIndex, it's
template[template.startIndex..<template.endIndex]
or shorter
template[template.startIndex...]
I have a lot of strings like this one:
"substring1:substring2:...:substring9"
So the number of substrings in string is always 9, and some substrings in string may be empty.
I want to split the string by ":" into array of strings and i do it like this:
let separator = Character(":")
let arrayOfStrings = string.split(separator: separator, maxSplits: 8, omittingEmptySubsequences: false).map({ String($0) })
For example for 13.5k strings it took about 150ms to convert them into arrays of strings.
Is there any other method that is more efficient in terms of time for this task?
Try this:
let arrayOfStrings = string.components(separatedBy: ":")
This should improve performance as it doesn't use .map(), which isn't really required in your case.
Or
As #Martin R suggested, if you can work with an array of SubString instead, the following should perform better:
let arrayOfStrings = string.split(separatedBy: ":")
split returns [Substring] which only uses references, does not allocate a new String and should be faster.
Also, .split is a method on String, (unlike .component which is a method on NSString) and hence there is no bridging conversion as pointed by #JeremyP.
I am using Swift 4.2. I am getting extraneous characters when formatting one string (s1) from another string(s0) using the %# format code.
I have searched extensively for details of string formatting but have come up with only partial answers including the code in the second line below. I need to be able to format s1 so that I can customize output from a Swift process. I ask this because I have not found an answer while searching for ways to format a string from a string.
I tried the following three statements:
let s0:[String] = ["abcdef"]
let s1:[String] = [String(format:"%#",s0)]
print(s1)
...
The output is shown below. It may not be clear, here, but there are four leading spaces to the left of the abcdef string.
["(\n abcdef\n)"]
How can I format s1 so it does not include the brackets, the \n escape characters, and the leading spaces?
The issue here is you are using an array but a string in s0.
so the following index will help you.
let s0:[String] = ["abcdef"]
let s1:[String] = [String(format:" %#",s0[0])]
I am getting extraneous characters when formatting one string (s1) from another string (s0) ...
The s0 is not a string. It is an array of strings (i.e. the square brackets of [String] indicate an array and is the same as saying Array<String>). And your s1 is also array, but one that that has one element, whose value is the string representation of the entire s0 array of strings. That’s obviously not what you intended.
How can I format s1 so it does not include the brackets, the \n escape characters, and the leading spaces?
You’re getting those brackets because s1 is an array. You’re getting the string with the \n and spaces because its first value is the string representation of yet another array, s0.
So, if you’re just trying to format a string, s0, you can do:
let s0: String = "abcdef"
let s1: String = String(format: "It is ‘%#’", s0)
Or, if you really want an array of strings, you can call String(format:) for each using the map function:
let s0: [String] = ["abcdef", "ghijkl"]
let s1: [String] = s0.map { String(format: "It is ‘%#’", $0) }
By the way, in the examples above, I didn’t use a string format of just %#, because that doesn’t accomplish anything at all, so I assumed you were formatting the string for a reason.
FWIW, we generally don’t use String(format:) very often. Usually we do “string interpolation”, with \( and ):
let s0: String = "abcdef"
let s1: String = "It is ‘\(s0)’"
Get rid of all the unneccessary arrays and let the compiler figure out the types:
let s0 = "abcdef" // a string
let s1 = String(format:"- %# -",s0) // another string
print(s1) // prints "- abcdef -"
I'm trying to remove the last numbers of an IP address string in Swift so I can loop through IP addresses. For instance if my variable = 192.168.1.123, I would like to trim the string to equal 192.169.1.
I'm not sure how to do this since some IP addresses will end in 1, 2 or 3 digits. I couldn't figure out how to trim back to a certain character.
I have a solution (In your case only). You can try it
let str = "192.168.1.123"
var arr = str.components(separatedBy: ".")
arr.removeLast()
let newstr = arr.joined(separator: ".") + "."
You can find the range of the last .:
let ip = "192.168.1.123"
let lastdot = ip.range(of: ".", options: .backwards)!
let base = ip[...lastdot.lowerBound]
This code assumes there is at least one . in the string. If not it will crash. That is easily fixed with proper use of if let.
base will be a Substring so depending on what you do next, you may need to wrap that as:
let base = String(ip[...lastdot.lowerBound])
Whether explicitly converting to String depends on whether subsequent methods require String or StringProtocol. Converting to String copies over the storage again, which is costly and unnecessary for many operations, but may be required in some cases.
How is it possible to endIndex and count of a String be different in swift2? its the code sample that I've used.it's not happen when all characters are english only.
print("count:",self.Label.text!.characters.count)
print("endIndex:",self.Label.text!.characters.endIndex)
print("String:",self.Label.text!)
output :
count: 32
endIndex: 34
String: • (دستور زبان) مفعولبه، مفعولعنه
The raw value of String.CharacterView.Index is irrelevant and should not be used. Its raw value only has meaning from within String and CharacterView.
In your case, some Unicode characters are merely combining characters that modify adjacent characters to form a single grapheme. For example, U+0300, Combining Grave Accent:
let str = "i\u{0300}o\u{0300}e\u{0300}"
print("String:",str)
print("count:",str.characters.count)
print("endIndex:",str.characters.endIndex)
var i = str.characters.startIndex
while i < str.characters.endIndex
{
print("\(i):\(str.characters[i])")
i = i.successor()
}
results in
String: ìòè
count: 3
endIndex: 6
0:ì
2:ò
4:è