【译】Swift 字符串速查表
【译】Swift 字符串速查表

本文由CocoaChina译者星夜暮晨翻译
Swift 的字符串 API 似乎让人难以习惯。此外,每次 Swift 与其标准库版本更新的时候,字符串的 API 也时不时会发生改变。你在 Stack Overflow 上寻找到的 Swift 1.2 解决方案往往不能在 Swift 2 上按照预期(甚至完全不能)使用。虽然从好的方面来看,我发现苹果的官方文档是非常有用的(参见本文底部的链接),但是出于备查的目的以及为了帮助仍挣扎于其中的人们,在此我仍旧了列出一系列的 String 代码片段:
(Gist和我 Github 仓库中的 Playground都已提供)
字符串初始化
创建一个字符串对象有无数种方式可以使用,包括字面量、从其他 Swift 类型转换、Unicode等等。
|
1
2
3
4
5
6
7
8
9
10
11
|
var emptyString = "" // 空字符串var stillEmpty = String() // 另一种空字符串的形式let helloWorld = "Hello World!" // 字符串字面量let a = String(true) // 由布尔值转换为:"true"let b: Character = "A" // 显式创建一个字符类型let c = String(b) // 从字符 "A" 转换let d = String(3.14) // 从 Double 类型转换为 "3.14"let e = String(1000) // 从 Int 类型转换为 "1000"let f = "Result = \(d)" // 字符串插值 "Result = 3.14"let g = "\u{2126}" // Unicode 字符,欧米伽符号 Ωlet h = String(count:3, repeatedValue:b) // 重复字符组成的字符串 "AAA" |
字符串是值类型
字符串是值类型(Value Type),当用其赋值或者函数传参的时候它会被拷贝(copied)。所拷贝的值在修改的时候是懒加载的(lazy)。
|
1
2
3
4
|
var aString = "Hello"var bString = aStringbString += " World!" // "Hello World!"print("\(aString)") // "Hello\n" |
字符串检测(空值、等值以及次序)
检测一个字符串是否为空:
|
1
|
emptyString.isEmpty // true |
Swift 是支持 Unicode 编码的,因此相等运算符("==")将会判断 Unicode 的范式是否等价(canonical equivalence)。这意味着对于两个字符串来说,如果拥有相同的语义(linguistic meaning)和表现形式的话,即使它们由不同 Unicode 标量(scalar)组成,那么也认为这两个字符串相等:
|
1
2
3
4
5
6
|
let spain = "Espa?a"let tilde = "\u{303}"let country = "Espan" + "\(tilde)" + "a"if country == spain { print("满足匹配!") // "满足匹配!\n"} |
比较次序的话:
|
1
2
3
|
if "aaa" < "bbb" { print("aaa")} |
前缀/后缀检测
检测一个字符串是否拥有某个前缀或者后缀:
|
1
2
3
|
let line = "0001 这里放上一些测试数据 %%%%"line.hasPrefix("0001") // trueline.hasSuffix("%%%%") // true |
大小写互相转换
顾名思义:
|
1
2
3
|
let mixedCase = "AbcDef"let upper = mixedCase.uppercaseString // "ABCDEF"let lower = mixedCase.lowercaseString // "abcdef" |
字符集合
字符串并不是某种编码的字符集合(collection views),但是它可以通过相应的属性为不同的编码形式提供所对应的字符集合。
|
1
2
3
4
|
country.characters // characterscountry.unicodeScalars // Unicode scalar 21-bit codescountry.utf16 // UTF-16 编码country.utf8 // UTF-8 编码 |
字符总数
字符串并没有一个直接的属性用以返回其包含的字符总数,因为字符总数只对特定的编码形式来说才有意义。因此,字符总数需要通过不同编码的字符集合来访问:
|
1
2
3
4
5
|
// spain = Espa?aprint("\(spain.characters.count)") // 6print("\(spain.unicodeScalars.count)") // 6print("\(spain.utf16.count)") // 6print("\(spain.utf8.count)") // 7 |
使用索引来访问字符集合
每个字符集合都拥有“索引”,可以通过它来访问整个集合中的元素。这或许是在使用字符串过程中碰到的最大难点之一了。你不能使用下标语法来访问字符串中的任意元素(比如说string[5])。
要遍历某个集合中的所有元素的时候(从现在开始我都将使用 characters 集合),可以通过 for...in 循环来进行:
|
1
2
3
4
|
var sentence = "Never odd or even"for character in sentence.characters { print(character)} |
每个集合都有两个实例属性,你可以在集合中使用它们来进行索引,就如同下标语法哪样:
startIndex:返回首个元素的位置,如果为空,那么和 endIndex 的值相同。
endIndex:返回字符串逾尾(past the end)的位置。
注意到如果使用 endIndex 的话,就意味着你不能直接将其作为下标来进行使用,因为这会导致越界。
|
1
2
3
|
let cafe = "café"cafe.startIndex // 0cafe.endIndex // 4 - 最后一个字符之后的位置 |
当通过以下几种方法进行字符串修改的时候,startIndex 和 endIndex 就变得极其有用:
successor():获取下一个元素
predecessor():获取上一个元素
advancedBy(n):向前或者向后跳 n 个元素
下面是一些用例,注意到如果必要的话你可以将操作串联起来:
|
1
2
3
4
5
6
7
|
cafe[cafe.startIndex] // "c"cafe[cafe.startIndex.successor()] // "a"cafe[cafe.startIndex.successor().successor()] // "f"// 注意到 cafe[endIndex] 会引发运行时错误cafe[cafe.endIndex.predecessor()] // "é"cafe[cafe.startIndex.advancedBy(2)] // "f" |
Indices 属性将返回字符串中所有元素的范围,这在遍历集合的时候很有用:
|
1
2
3
|
for index in cafe.characters.indices { print(cafe[index])} |
你无法使用某个字符串中的索引来访问另一个字符串。你可以通过 distanceTo 方法将索引转换为整数值:
|
1
2
3
4
5
|
let word1 = "ABCDEF"let word2 = "012345"let indexC = word1.startIndex.advancedBy(2)let distance = word1.startIndex.distanceTo(indexC) // 2let digit = word2[word2.startIndex.advancedBy(distance)] // "2" |
范围的使用
要检出字符串集合中某个范围内的元素的话,可以使用范围。范围可以通过 start 和 end 索引来完成创建:
|
1
2
3
4
|
let fqdn = "useyourloaf.com"let rangeOfTLD = Range(start: fqdn.endIndex.advancedBy(-3), end: fqdn.endIndex)let tld = fqdn[rangeOfTLD] // "com" |
使用 "..." 或者 "..<" 运算符可以快速完成范围的创建:
通过索引或者范围来截取字符串
要通过索引或者范围来截取字符串的话,有许多方法:
获取前缀或者后缀
如果你需要得到或者抛弃字符串前面或者后面的某些元素的话,可以:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
let digits = "0123456789"let tail = String(digits.characters.dropFirst()) // "123456789"let less = String(digits.characters.dropFirst(3)) // "23456789"let head = String(digits.characters.dropLast(3)) // "0123456"let prefix = String(digits.characters.prefix(2)) // "01"let suffix = String(digits.characters.suffix(2)) // "89"let index4 = digits.startIndex.advancedBy(4)let thru4 = String(digits.characters.prefixThrough(index4)) // "01234"let upTo4 = String(digits.characters.prefixUpTo(index4)) // "0123"let from4 = String(digits.characters.suffixFrom(index4)) // "456789" |
插入或删除
要在指定位置插入字符的话,可以通过索引:
|
1
2
3
|
var stars = "******"stars.insert("X", atIndex: stars.startIndex.advancedBy(3))// "***X***" |
要在索引出插入字符串的话,那么需要将字符串转换为字符集:
|
1
2
|
stars.insertContentsOf("YZ".characters, at: stars.endIndex.advancedBy(-3))// "***XYZ***" |
范围替换
要替换一个范围的字符串内容的话:
添加元素
可以通过“+”运算符将字符串相互连接起来,也可以使用 appendContentsOf 方法:
|
1
2
3
|
var message = "Welcome"message += " Tim" // "Welcome Tim"message.appendContentsOf("!!!") // "Welcome Tim!!! |
移除或者返回指定索引的元素
从一个字符串当中移除某个元素,需要注意这个方法将会使该字符串此前所有的任何索引标记(indice)失效:
|
1
2
3
|
var grades = "ABCDEF"let ch = grades.removeAtIndex(grades.startIndex) // "A"print(grades) // "BCDEF" |
范围移除
移除字符集中某个范围的字符,需要主要的是这个方法同样也会使索引标记失效:
|
1
2
3
|
var sequences = "ABA BBA ABC"let midRange = sequences.startIndex.advancedBy(4)...sequences.endIndex.advancedBy(-4)sequences.removeRange(midRange) // "ABA ABC" |
与 NSString 桥接
String 可以转换为 NSString 从而与 Objective-C 桥接。如果 Swift 标准库没有你所需要的功能的话,那么导入 Foundation 框架,通过 NSString 来访问这些你所需要的方法。
请注意这个桥接方法并不是无损的,因此尽可能使用 Swift 标准库完成大部分功能。
|
1
2
3
4
|
// 不要忘记导入 Foundationimport Foundationlet welcome = "hello world!"welcome.capitalizedString // "Hello World!" |
检索内含的字符串
使用 NSString 方法的一个例子就是执行内含字符串的检索:
|
1
2
3
4
5
6
|
let text = "123045780984"if let rangeOfZero = text.rangeOfString("0", options: NSStringCompareOptions.BackwardsSearch) { // 寻找“0”元素,然后获取之后的元素 let suffix = String(text.characters.suffixFrom(rangeOfZero.endIndex)) // "984"} |
Playgournd
我发现在 Xcode 中通过 Playground 来熟悉 API 是一个非常好的选择。如果你想要抢先体验一下所有这些功能的话,这个文章的 Playground 可以从我的 Github 仓库中下载。
拓展阅读
【译】Swift 字符串速查表的更多相关文章
- Java, C#, Swift语法对比速查表
原文:Java, C#, Swift语法对比速查表 Java 8 C# 6 Swift 变量 类型 变量名; 类型 变量名; var 变量名 : 类型; 变量(类型推断) N/A var 变量名= ...
- .htaccess下Flags速查表
Flags是可选参数,当有多个标志同时出现时,彼此间以逗号分隔. 速查表: RewirteRule 标记 含义 描述 R Redirect 发出一个HTTP重定向 F Forbidden 禁止对URL ...
- OpenStack 命令行速查表
OpenStack 命令行速查表 updated: 2017-07-18 08:53 Contents 认证 (keystone) 镜像(glance) 计算 (nova) 实例的暂停.挂起.停止 ...
- 【转】shell速查表
shell速查表 转自:https://www.jianshu.com/p/a98a334bfb25 1. 变量 #!/bin/bash msg="hello world" ech ...
- GNU Emacs命令速查表
GNU Emacs命令速查表 第一章 Emacs的基本概念 表1-1:Emacs编辑器的主模式 模式 功能 基本模式(fundamental mode) 默认模式,无特殊行为 文本模式(text m ...
- vim基本命令速查表
来源:https://github.com/skywind3000/awesome-cheatsheets/blob/master/editors/vim.txt ################## ...
- bash基本命令速查表
来源:https://github.com/skywind3000/awesome-cheatsheets/blob/master/languages/bash.sh ################ ...
- 【转】正则表达式速查表(http://www.jb51.net/shouce/jquery1.82/regexp.html)
正则表达式速查表 字符 描述 \ 将下一个字符标记为一个特殊字符.或一个原义字符.或一个向后引用.或一个八进制转义符.例如,“n”匹配字符“n”.“\n”匹配一个换行符.串行“\\”匹配“\”而“\( ...
- Bash中文速查表
最好用的中文速查表(Cheatsheet) 来源:https://github.com/skywind3000/awesome-cheatsheets 感谢网友们的贡献! ############## ...
随机推荐
- bzoj 3158: 千钧一发【最小割】
这个条件非常妙啊,奇数和奇数一定满足1,因为\( (2a+1)^2+(2b+1)^2=4a^2+4a+4b^2+4b+2=2(2(a^2+a+b^2+b)+1) \)里面这个一定不是平方数因为除二后是 ...
- 多线程中join()
这个鬼东西百度了好久没弄明白,大佬们代码一粘贴好了完事,借助官方api终于是理解了,当然如果有问题欢迎大家用键盘来羞辱我. 首先 join有什么用? 他是用来确定线程何时结束的 , Thread ...
- mysql 5.5.58 tar包安装部署
环境: centos 7.4 64位 mysql 版本,5.5.58 glibc 64 位版,下载地址:https://dev.mysql.com/downloads/mysql/5.5.html#d ...
- perl C/C++ 扩展(一)
通过h2xs 中间件,我们可以快速的使用c或则C++ 库来实现perl 扩展功能 第一讲:跑通hello world 程序******************************我们使用命令:h2 ...
- 使用CSS 实现菱形图片,斜条纹背景
比较简单的菱形图片: 效果如下 代码部分: <div class="d1"> <img src="img/5.jpg"> </di ...
- chrome浏览器历史版本
持续更新中······ google-chrome 浏览器 win64位 版本号 大小 官网更新日期 66.0.3359.181 48.58 MB 2018年5月16日 65.0.3325.181 4 ...
- python学习之串口编程
# coding=utf-8import serial ser=serial.Serial('com1',9600)ser.write(b"hello")while 1: ser. ...
- JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
contextmenu事件 该事件用以表示何时应该显示上下文菜单,以便开发者取消默认的上下文菜单,转而提供自定义的菜单. 因为该事件属于鼠标事件,所以其事件对象中包含与光标位置有关的所有属性.如: & ...
- 解决java.lang.NoClassDefFoundError: javax/xml/rpc/service错误的方法
最近在做WebService项目,本地测试没有问题,打算部署到服务器上,但是部署后,访问时出现了如下图1的错误: 图1 图1报的是没有找到定义的类的错误.刷新页面有又出现了另外“新”的错误: 图2 根 ...
- 安卓4.4不支持touchend事件解决办法
最近的项目要求兼容到OPPO A31这款手机,这款手机是安卓4.4,调试时遇到了touch手指不能滑动页面切换的问题,最终解决通过在touchstart事件里面加上一个 event.preventDe ...