字符串子字符串在 Swift 中是如何工作的 [英] How does String substring work in Swift

查看:62
本文介绍了字符串子字符串在 Swift 中是如何工作的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在用 Swift 3 更新我的一些旧代码和答案,但是当我使用 Swift 字符串和索引子字符串时,事情变得混乱了.

具体来说,我正在尝试以下操作:

let str = "你好,操场"let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)让前缀 = str.substringWithRange(prefixRange)

第二行给我以下错误

<块引用>

'String' 类型的值没有成员 'substringWithRange'

我看到 String 现在确实有以下方法:

str.substring(to: String.Index)str.substring(来自:String.Index)str.substring(with: Range)

一开始这些真的让我很困惑,所以我开始玩

以下所有例子都使用

var str = "你好,操场"

斯威夫特 4

字符串在 Swift 4 中得到了很大的改进.当你现在从字符串中获取一些子字符串时,你会返回一个 Substring 类型而不是 String.为什么是这样?字符串是 Swift 中的值类型.这意味着如果你使用一个 String 来创建一个新的,那么它必须被复制.这有利于稳定性(没有其他人会在您不知情的情况下对其进行更改),但对效率不利.

另一方面,子字符串是对它来自的原始字符串的引用.这是 .子字符串(作为一种类型)是短暂的.

Swift 4 的另一个重大改进是字符串是集合(再次).这意味着无论您可以对 Collection 做什么,您都可以对 String 做(使用下标、迭代字符、过滤器等).

以下示例展示了如何在 Swift 中获取子字符串.

获取子串

您可以使用下标或许多其他方法(例如,prefixsuffixsplit)从字符串中获取子字符串).不过,您仍然需要对范围使用 String.Index 而不是 Int 索引.(如果您需要帮助,请参阅我的其他答案.)

字符串的开头

您可以使用下标(注意 Swift 4 的单边范围):

let index = str.index(str.startIndex, offsetBy: 5)let mySubstring = str[..<index]//你好

前缀:

let index = str.index(str.startIndex, offsetBy: 5)let mySubstring = str.prefix(upTo: index)//你好

甚至更简单:

let mySubstring = str.prefix(5)//你好

字符串结束

使用下标:

let index = str.index(str.endIndex, offsetBy: -10)let mySubstring = str[index...]//游乐场

后缀:

let index = str.index(str.endIndex, offsetBy: -10)let mySubstring = str.suffix(from: index)//操场

甚至更简单:

let mySubstring = str.suffix(10)//操场

请注意,在使用 suffix(from: index) 时,我必须使用 -10 从末尾开始倒数.仅使用 suffix(x) 时不需要这样做,它只需要字符串的最后一个 x 字符.

字符串中的范围

我们再次在这里简单地使用下标.

let start = str.index(str.startIndex, offsetBy: 7)让 end = str.index(str.endIndex, offsetBy: -6)让范围=开始..<结束let mySubstring = str[range]//播放

Substring 转换为String

不要忘记,当您准备保存子字符串时,您应该将其转换为String,以便可以清理旧字符串的内存.

让 myString = String(mySubstring)

使用 Int 索引扩展?

在阅读文章 Swift 3 中的字符串 作者:Airspeed Velocity 和 Ole Begemann.尽管在 Swift 4 中,字符串是集合,但 Swift 团队故意没有使用 Int 索引.它仍然是 String.Index.这与 Swift 字符由不同数量的 Unicode 代码点组成有关.必须为每个字符串唯一计算实际索引.

我不得不说,我希望 Swift 团队在未来找到一种方法来抽象出 String.Index.但在他们之前,我选择使用他们的 API.它帮助我记住字符串操作不仅仅是简单的 Int 索引查找.

I've been updating some of my old code and answers with Swift 3 but when I got to Swift Strings and Indexing with substrings things got confusing.

Specifically I was trying the following:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

where the second line was giving me the following error

Value of type 'String' has no member 'substringWithRange'

I see that String does have the following methods now:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

These were really confusing me at first so I started playing around

All of the following examples use

var str = "Hello, playground"

Swift 4

Strings got a pretty big overhaul in Swift 4. When you get some substring from a String now, you get a Substring type back rather than a String. Why is this? Strings are value types in Swift. That means if you use one String to make a new one, then it has to be copied over. This is good for stability (no one else is going to change it without your knowledge) but bad for efficiency.

A Substring, on the other hand, is a reference back to the original String from which it came. Here is an image from the documentation illustrating that.

No copying is needed so it is much more efficient to use. However, imagine you got a ten character Substring from a million character String. Because the Substring is referencing the String, the system would have to hold on to the entire String for as long as the Substring is around. Thus, whenever you are done manipulating your Substring, convert it to a String.

let myString = String(mySubstring)

This will copy just the substring over and the memory holding old String can be reclaimed. Substrings (as a type) are meant to be short lived.

Another big improvement in Swift 4 is that Strings are Collections (again). That means that whatever you can do to a Collection, you can do to a String (use subscripts, iterate over the characters, filter, etc).

The following examples show how to get a substring in Swift.

Getting substrings

You can get a substring from a string by using subscripts or a number of other methods (for example, prefix, suffix, split). You still need to use String.Index and not an Int index for the range, though. (See my other answer if you need help with that.)

Beginning of a string

You can use a subscript (note the Swift 4 one-sided range):

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello

or prefix:

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello

or even easier:

let mySubstring = str.prefix(5) // Hello

End of a string

Using subscripts:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground

or suffix:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground

or even easier:

let mySubstring = str.suffix(10) // playground

Note that when using the suffix(from: index) I had to count back from the end by using -10. That is not necessary when just using suffix(x), which just takes the last x characters of a String.

Range in a string

Again we simply use subscripts here.

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

Converting Substring to String

Don't forget, when you are ready to save your substring, you should convert it to a String so that the old string's memory can be cleaned up.

let myString = String(mySubstring)

Using an Int index extension?

I'm hesitant to use an Int based index extension after reading the article Strings in Swift 3 by Airspeed Velocity and Ole Begemann. Although in Swift 4, Strings are collections, the Swift team purposely hasn't used Int indexes. It is still String.Index. This has to do with Swift Characters being composed of varying numbers of Unicode codepoints. The actual index has to be uniquely calculated for every string.

I have to say, I hope the Swift team finds a way to abstract away String.Index in the future. But until them I am choosing to use their API. It helps me to remember that String manipulations are not just simple Int index lookups.

这篇关于字符串子字符串在 Swift 中是如何工作的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆