当前位置: 首页 > 知识库问答 >
问题:

String子字符串如何在Swift中工作

支淮晨
2023-03-14

我一直在用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>)

起初我真的很困惑,所以我开始围绕索引和范围玩。这是子串的后续问答。我在下面添加一个答案来展示它们是如何使用的。

共有2个答案

娄鹤轩
2023-03-14

我对斯威夫特的字符串访问模型感到非常失望:一切都必须是索引。我只想使用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
刘翔宇
2023-03-14

以下所有示例都使用

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语法之前,代码如下所示: