我一直在用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>)
起初我真的很困惑,所以我开始围绕索引和范围玩。这是子串的后续问答。我在下面添加一个答案来展示它们是如何使用的。
我对斯威夫特的字符串访问模型感到非常失望:一切都必须是索引。我只想使用Int访问字符串的第I个字符,而不是笨拙的索引和前进(每次主要版本都会发生变化)。因此,我对字符串进行了扩展:
extension String {
func index(from: Int) -> Index {
return self.index(startIndex, offsetBy: from)
}
func substring(from: Int) -> String {
let fromIndex = index(from: from)
return String(self[fromIndex...])
}
func substring(to: Int) -> String {
let toIndex = index(from: to)
return String(self[..<toIndex])
}
func substring(with r: Range<Int>) -> String {
let startIndex = index(from: r.lowerBound)
let endIndex = index(from: r.upperBound)
return String(self[startIndex..<endIndex])
}
}
let str = "Hello, playground"
print(str.substring(from: 7)) // playground
print(str.substring(to: 5)) // Hello
print(str.substring(with: 7..<11)) // play
以下所有示例都使用
var str = "Hello, playground"
弦乐在Swift 4中得到了相当大的改进。当你现在从一个字符串中得到一些子字符串时,你会得到一个返回的子字符串,而不是一个字符串。为什么会这样?字符串是Swift中的值类型。这意味着如果你使用一个字符串来创建一个新的字符串,那么它必须被复制过来。这有利于稳定性(在你不知情的情况下,没有人会改变它),但不利于效率。
另一方面,子字符串是对其来源的原始字符串的引用。这是一张来自文档的图像,说明了这一点。
无需复制,因此使用效率更高。然而,假设你从一个百万字符的字符串中得到了一个十个字符的子字符串。因为子字符串引用字符串,所以只要子字符串还在,系统就必须保持整个字符串。因此,无论何时操作完子字符串,都要将其转换为字符串。
let myString = String(mySubstring)
这将只复制子字符串,并且可以回收保存旧字符串的内存。子字符串(作为一种类型)的寿命很短。
Swift 4的另一个重大改进是字符串是集合(再次)。这意味着您可以对集合执行任何操作,也可以对字符串执行任何操作(使用下标、迭代字符、过滤器等)。
以下示例显示了如何在Swift中获取子字符串。
您可以使用下标或许多其他方法(例如,前缀、后缀、拆分)从字符串中获取子字符串。您仍然需要使用字符串。索引,而不是范围的索引。(如果需要帮助,请参阅我的另一个答案。)
您可以使用下标(注意Swift 4单侧范围):
let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello
或前缀:
let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello
甚至更简单:
let mySubstring = str.prefix(5) // Hello
使用下标:
let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground
或后缀:
let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground
甚至更简单:
let mySubstring = str.suffix(10) // playground
注意,当使用后缀(from:index)时,我必须使用-10从末尾倒数。当只使用后缀(x)时,这是不必要的,后缀只取字符串的最后一个字符。
同样,我们在这里简单地使用下标。
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
let mySubstring = str[range] // play
不要忘记,当您准备好保存子字符串时,您应该将其转换为String
,以便清理旧字符串的内存。
let myString = String(mySubstring)
在阅读了AirSpeed VelSpeed和Ole Begemann的文章《Swift 3中的字符串》后,我对使用基于Int
的索引扩展犹豫不决。尽管在Swift 4中,字符串是集合,但Swift团队故意没有使用Int
索引。它仍然是String。索引
。这与Swift字符由不同数量的Unicode代码点组成有关。必须为每个字符串唯一计算实际索引。
我不得不说,我希望Swift团队将来能找到一种方法来抽象出String。索引
。但在那之前,我选择使用他们的API。它帮助我记住字符串操作不仅仅是简单的Int
索引查找。
Swift 提供了一种高性能的、兼容 Unicode 的字符串实现,这也成为了它自身标准库的一部分。在 Swift 2 中, String 类型不再遵守 CollectionType 协议,那时 String 是 Character 类型的集合,就像是数组。现在 String 提供了一种公开字符集合视图的字符属性。 为什么要这么改变?字符串作为字符的集合, String 类型的行为和数组、集合以及
问题内容: 我曾经在JavaScript中这样做: Swift没有此功能,如何做类似的事情? 问题答案: 编辑/更新: Xcode 11•Swift 5.1或更高版本 用法: 不区分大小写的样本 正则表达式样本
问题内容: let string = “hello hi” var hello = “” var hi = “” 我不会分割字符串,以便hello的值获得“ hello”,hi的值获得“ hi” 问题答案: 试试这个: 字符串的名称在哪里,并且包含由空格分隔的组件。 然后,您可以将组件获取为: Doc:componentsSeparatedByString 编辑: 对于Swift 3,以上将是:
问题内容: 如何在Swift中连接字符串? 在我们喜欢 要么 但是我想用Swift语言做到这一点。 问题答案: 您可以通过多种方式连接字符串: 您也可以这样做: 我相信还有更多方法。 描述位 创建一个常数。(有点像)。设置后就无法更改其值。您仍然可以将其添加到其他东西并创建新变量。 创建一个变量。(有点像),因此您可以更改其值。 注意 在现实中,并有 很大的不同 ,从和,但它可以帮助类比。
我不想拆分我的字符串,以便hello的值得到“hello”,而hi的值得到“hi”
问题内容: 我的主字符串是“ hello Swift Swift和Swift”,子字符串是Swift。我需要获取子字符串“ Swift”在提到的字符串中出现的次数。 此代码可以确定模式是否存在。 现在我需要知道发生的次数。 问题答案: 一种简单的方法是分割,然后从零件数中减去1: 此代码打印3。 编辑: 在Swift 3语法之前,代码如下所示: