我一直在更新我的一些旧代码和答案与Swift 3,但当我得到Swift字符串和索引子字符串的事情变得令人困惑。
具体来说,我尝试了以下几点:
let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)
第二行给出了如下错误
String类型的值没有成员substringWithRange
我看到String现在确实有以下方法:
str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)
这些一开始让我很困惑,所以我开始摆弄索引和范围。这是子字符串的后续问题和答案。我在下面添加了一个答案来说明它们是如何使用的。
String的特殊性在其他答案中已经讨论过了。解释一下:字符串有一个特定的索引,它不是Int类型,因为字符串元素在一般情况下没有相同的大小。因此,String不符合RandomAccessCollection,访问特定索引意味着遍历集合,这不是O(1)操作。
许多答案都提出了使用范围的变通方法,但它们会导致代码效率低下,因为它们使用的String方法(index(from:), index(:offsetBy:),…)不是O(1)。
要像在数组中一样访问字符串元素,您应该使用array:
let array = Array("Hello, world!")
let letter = array[5]
这是一个权衡,数组创建是一个O(n)操作,但数组访问是O(1)。当你想用String(数组)时,你可以转换回String。
Swift 4和5:
extension String {
subscript(_ i: Int) -> String {
let idx1 = index(startIndex, offsetBy: i)
let idx2 = index(idx1, offsetBy: 1)
return String(self[idx1..<idx2])
}
subscript (r: Range<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return String(self[start ..< end])
}
subscript (r: CountableClosedRange<Int>) -> String {
let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let endIndex = self.index(startIndex, offsetBy: r.upperBound - r.lowerBound)
return String(self[startIndex...endIndex])
}
}
如何使用:
"abcde"[0] -> "a"
“中的”[0…2]——>“abc”
”中的“[2 . .<4]——> "cd"
Swift 5解决方案高性能
let fromIndex = s.index(s.startIndex, offsetBy: fromIndex)
let toIndex = s.index(s.startIndex, offsetBy: toIndex)
我使用这种方法从一个fromIndex到toIndex的Leetcode问题获得子字符串,它超时了,似乎这是非常低效和缓慢的,并导致了超时。
一个更快的纯Swift方式来完成这个是:
let fromIndex = String.Index(utf16Offset:fromIndex, in: s)
let toIndex = String.Index(utf16Offset: toIndex, in: s)
String的特殊性在其他答案中已经讨论过了。解释一下:字符串有一个特定的索引,它不是Int类型,因为字符串元素在一般情况下没有相同的大小。因此,String不符合RandomAccessCollection,访问特定索引意味着遍历集合,这不是O(1)操作。
许多答案都提出了使用范围的变通方法,但它们会导致代码效率低下,因为它们使用的String方法(index(from:), index(:offsetBy:),…)不是O(1)。
要像在数组中一样访问字符串元素,您应该使用array:
let array = Array("Hello, world!")
let letter = array[5]
这是一个权衡,数组创建是一个O(n)操作,但数组访问是O(1)。当你想用String(数组)时,你可以转换回String。