我一直在更新我的一些旧代码和答案与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>)
这些一开始让我很困惑,所以我开始摆弄索引和范围。这是子字符串的后续问题和答案。我在下面添加了一个答案来说明它们是如何使用的。
同样的挫折,这应该不难…
我编译了这个从较大文本中获取子字符串位置的示例:
//
// Play with finding substrings returning an array of the non-unique words and positions in text
//
//
import UIKit
let Bigstring = "Why is it so hard to find substrings in Swift3"
let searchStrs : Array<String>? = ["Why", "substrings", "Swift3"]
FindSubString(inputStr: Bigstring, subStrings: searchStrs)
func FindSubString(inputStr : String, subStrings: Array<String>?) -> Array<(String, Int, Int)> {
var resultArray : Array<(String, Int, Int)> = []
for i: Int in 0...(subStrings?.count)!-1 {
if inputStr.contains((subStrings?[i])!) {
let range: Range<String.Index> = inputStr.range(of: subStrings![i])!
let lPos = inputStr.distance(from: inputStr.startIndex, to: range.lowerBound)
let uPos = inputStr.distance(from: inputStr.startIndex, to: range.upperBound)
let element = ((subStrings?[i])! as String, lPos, uPos)
resultArray.append(element)
}
}
for words in resultArray {
print(words)
}
return resultArray
}
返回
("Why" 0,3)
("substrings", 26, 36)
(“Swift3”,40,46)
我的思维很机械。以下是一些基本常识……
斯威夫特4
斯威夫特5
let t = "abracadabra"
let start1 = t.index(t.startIndex, offsetBy:0)
let end1 = t.index(t.endIndex, offsetBy:-5)
let start2 = t.index(t.endIndex, offsetBy:-5)
let end2 = t.index(t.endIndex, offsetBy:0)
let t2 = t[start1 ..< end1]
let t3 = t[start2 ..< end2]
//or a shorter form
let t4 = t[..<end1]
let t5 = t[start2...]
print("\(t2) \(t3) \(t)")
print("\(t4) \(t5) \(t)")
// result:
// abraca dabra abracadabra
结果是一个子字符串,这意味着它是原始字符串的一部分。要得到一个完整的独立字符串,只需使用e.g.。
String(t3)
String(t4)
这是我所使用的:
let mid = t.index(t.endIndex, offsetBy:-5)
let firstHalf = t[..<mid]
let secondHalf = t[mid...]
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。
在上面的基础上,我需要在非打印字符处分割字符串,删除非打印字符。我开发了两种方法:
var str = "abc\u{1A}12345sdf"
let range1: Range<String.Index> = str.range(of: "\u{1A}")!
let index1: Int = str.distance(from: str.startIndex, to: range1.lowerBound)
let start = str.index(str.startIndex, offsetBy: index1)
let end = str.index(str.endIndex, offsetBy: -0)
let result = str[start..<end] // The result is of type Substring
let firstStr = str[str.startIndex..<range1.lowerBound]
我用上面的一些答案组合在一起。
因为字符串是一个集合,然后我做了以下工作:
var fString = String()
for (n,c) in str.enumerated(){
*if c == "\u{1A}" {
print(fString);
let lString = str.dropFirst(n + 1)
print(lString)
break
}
fString += String(c)
}*
这对我来说更直观。哪个是最好的?我不知道
它们都使用Swift 5