【译】Swift 字符串速查表

2015-12-18 10:32 编辑: suiling 分类:Swift 来源:CocoaChina翻译活动

10 5585


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 = aString
bString += " 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")    // true
line.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       // characters
country.unicodeScalars   // Unicode scalar 21-bit codes
country.utf16            // UTF-16 编码
country.utf8             // UTF-8 编码

字符总数

字符串并没有一个直接的属性用以返回其包含的字符总数,因为字符总数只对特定的编码形式来说才有意义。因此,字符总数需要通过不同编码的字符集合来访问:

1
2
3
4
5
// spain = Espa?a
print("\(spain.characters.count)")      // 6
print("\(spain.unicodeScalars.count)")  // 6
print("\(spain.utf16.count)")           // 6
print("\(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   // 0
cafe.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) // 2
let 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
// 不要忘记导入 Foundation
import Foundation
let 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 字符串速查表的更多相关文章

  1. Java, C#, Swift语法对比速查表

    原文:Java, C#, Swift语法对比速查表   Java 8 C# 6 Swift 变量 类型 变量名; 类型 变量名; var 变量名 : 类型; 变量(类型推断) N/A var 变量名= ...

  2. .htaccess下Flags速查表

    Flags是可选参数,当有多个标志同时出现时,彼此间以逗号分隔. 速查表: RewirteRule 标记 含义 描述 R Redirect 发出一个HTTP重定向 F Forbidden 禁止对URL ...

  3. OpenStack 命令行速查表

    OpenStack 命令行速查表   updated: 2017-07-18 08:53 Contents 认证 (keystone) 镜像(glance) 计算 (nova) 实例的暂停.挂起.停止 ...

  4. 【转】shell速查表

    shell速查表 转自:https://www.jianshu.com/p/a98a334bfb25 1. 变量 #!/bin/bash msg="hello world" ech ...

  5. GNU Emacs命令速查表

    GNU Emacs命令速查表 第一章  Emacs的基本概念 表1-1:Emacs编辑器的主模式 模式 功能 基本模式(fundamental mode) 默认模式,无特殊行为 文本模式(text m ...

  6. vim基本命令速查表

    来源:https://github.com/skywind3000/awesome-cheatsheets/blob/master/editors/vim.txt ################## ...

  7. bash基本命令速查表

    来源:https://github.com/skywind3000/awesome-cheatsheets/blob/master/languages/bash.sh ################ ...

  8. 【转】正则表达式速查表(http://www.jb51.net/shouce/jquery1.82/regexp.html)

    正则表达式速查表 字符 描述 \ 将下一个字符标记为一个特殊字符.或一个原义字符.或一个向后引用.或一个八进制转义符.例如,“n”匹配字符“n”.“\n”匹配一个换行符.串行“\\”匹配“\”而“\( ...

  9. Bash中文速查表

    最好用的中文速查表(Cheatsheet) 来源:https://github.com/skywind3000/awesome-cheatsheets 感谢网友们的贡献! ############## ...

随机推荐

  1. ugui学习资料

    官网文档 http://docs.unity3d.com/Manual/index.html 官网视频教程http://unity3d.com/learn/tutorials/modules/begi ...

  2. C# interface 的特性 无法被implement class继承

    最近做interface添加特性后,implement class 无法继承. 微软要求class是实现Interface而不是继承,所以我们必须手动添加特性,而不能自动继承. 对于abstract ...

  3. 【渗透测试】如何使用burpsuite对特殊密码进行爆破

    爆破是渗透测试中必不可少的一部分,对于没有太大价值可利用的漏洞或是业务只有一个登陆页面时,爆破更是我们的最合适的选择.那么在爆破时,抛去目标系统对爆破频率的限制,如果遇到较为复杂的密码,该如何顺利进行 ...

  4. Syncd-开源自动化部署工具

    官网地址:https://gitee.com/dreamans/syncd/issues syncd是一款开源的代码部署工具,它具有简单.高效.易用等特点,可以提高团队的工作效率. 目前只支持类Lin ...

  5. vue 脚手架 图片预加载

    $('.back-img').onload =function(){ var img =new Image(); img.src = '../assets/dt-bj.png'; } 该组件内的图片加 ...

  6. python+selenium+requests爬取qq空间相册时遇到的问题及解决思路

    最近研究了下用python爬取qq空间相册的问题,遇到的问题及解决思路如下: 1.qq空间相册的访问需要qq登录并且需是好友,requests模块模拟qq登录略显麻烦,所以采用selenium的dri ...

  7. Unix高级环境编程之fcntl函数

    #include <fcntl.h> int fcntl(int fd, int cmd, ...) fcntl功能 复制一个现有的描述符 (cmd = F_DUPFD) ##### 返回 ...

  8. 现在的Unix时间戳(Unix timestamp)

    如何在不同编程语言中获取现在的Unix时间戳(Unix timestamp)? Java time JavaScript Math.round(new Date().getTime()/1000)ge ...

  9. Struts 2中访问Servlet API的几种方法小结

    1.使用ActionContext Action运行期间所用到的数据都保存在ActionContext中,例如session.客户端提交的参数等,ActionContext是Action的一个上下文对 ...

  10. 上白泽慧音——tarjian

    题目描述 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点.人间 ...