【译】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. Integrated Metabolomics and Lipidomics Analyses Reveal Metabolic Reprogramming in Human Glioma with IDH1 Mutation (文献分享一组-黄旭蕾)

    题目:Integrated Metabolomics and Lipidomics Analyses Reveal Metabolic Reprogramming in Human Glioma wi ...

  2. cmd - 使用curl命令的注意点

    前言 最近在cmd中使用curl命令来测试rest api,发现有不少问题,这里记录一下. 在cmd中使用curl命令的注意事项 json不能由单引号包括起来 json数据里的双引号要用反斜杠\转义 ...

  3. 1-zookeeper基本原理和使用

    1 分布式应用 1.1 分布式系统原理 在一个网络中,每台服务器上各跑一个应用,然后彼此连接起来就组成一套系统.比如提供完成的游戏服务,需要有认证应用,道具应用,积分应用,游戏主应用等,应用并非跑在一 ...

  4. Python 数字模块

    Python中的数字模块 math模块 random模块 Decimal模块 - 没有损失的小数 Fraction模块 - 可以计算分数

  5. CSS以及JS各种库的在线CDN引用地址

    JS类—— html5.js,让你的IE浏览器支持H5新特性:http://html5shiv.googlecode.com/svn/trunk/html5.js   (记得要注释判断哦) JQuer ...

  6. Django 使用allauth报错

    一:报错 RuntimeError: Model class django.contrib.sites.models.Site doesn't declare an explicit app_labe ...

  7. Jquery多选框互相内容交换

    <head runat="server"> <title>无标题页</title> <script type="text/jav ...

  8. Python3 配置文件(configparser)(转载)

    本文由 Luzhuo 编写,转发请保留该信息. 原文: http://blog.csdn.net/rozol/article/details/72793304 以下代码以Python3.6.1为例 L ...

  9. Spring mvc简单案例

    jar包 <!--junit--><dependency> <groupId>junit</groupId> <artifactId>jun ...

  10. 单线程异步回调机制的缺陷与node的解决方案

    一.node单线程异步的缺陷: 单线程异步的优点自然不必多说,node之所以能够如此快的兴起,其单线程异步回调机制相比于传统同步执行编程语言的优势便是原因之一.然而,开发一个node程序,其缺陷也是不 ...