美文网首页
字符串(一)

字符串(一)

作者: 小橘子成长记 | 来源:发表于2018-04-27 18:00 被阅读5次

    你已经了解了String是表示文本的类型。文本是一种非常常见的数据类型:人名;地址;一句话。所有这些都可能是应用程序需要处理的。所以我们需要更深入的了解字符串如何工作以及它能做什么。

    这一章会加深你对字符串的理解,更确切地说是了解字符串如何在Swift中工作的。Swift是少数能够正确处理Unicode字符的语言之一,同时可预测性最大(不懂什么意思)。

    Strings as collections(字符串集合)

    在第2章中,你学习了字符串的基础知识,并学习了字符集和代码点。他们将映射数字定义为它所代表的字符。现在让我们进一步研究字符串类型。

    将字符串概念化为字符的集合是非常容易的。因为字符串本来就是集合,像下面这样:

    let string = "Matt"
    for char instring {
      print(char)
    }
    

    分别打印出Matt的每个字符。很简单,是吗?你还可以使用其他的操作,例如:

    let stringLength = string.count 
    

    这将得到string的长度。

    现在假设你想要获得字符串中的第四个字符。你可以这样做。

    let fourthChar = string[3]
    

    但是,如果你这样做,你将收到以下错误消息:

    'subscript' is unavailable: cannot subscriptString with an Int,
    see the documentation comment for discussion
    

    这是为什么呢?因为他引入了一个字集群。

    Grapheme clusters字集群

    如你所知,字符串由Unicode字符的集合组成。到目前为止,你认为一个代码点恰好等于一个字符,反之亦然。然而,“字符”这个词是相当宽松的。

    比如有两种方式可以代表某些字符。其中的一个例子就是café里的é ,这是一个带有声调的e。你可以用一个字符或两个字符来表示这个字符。

    单个字符是代码点233。两个字符是一个单独的e,后面跟着一个声调字符,两个字符结合成一个字符,这是一个特殊的字符,他修改了前面的字符。

    QQ20180427-174854@2x.png

    在第二个图中,这两个字符的组合构成了一个由Unicode标准定义的字形集群。当你想到一个字符时,你实际上可能会想到一个字形集群。字形集群由Swift类型字符表示。

    组合字符的另一个例子是用来改变某些表情符号的皮肤颜色。例如:

    QQ20180427-174943@2x.png

    在这里,竖起大拇指的表情符号后面结合了肤色字符。在支持它的平台上,包括iOS和macOS,呈现的表情是一个单拇指向上的字符,颜色是肤色。

    现在让我们来看看当字符串被用作集合时,这意味着什么。思考下面的代码:

    let cafeNormal = "café"
    
    let cafeCombining = "cafe\u{0301}"
    
    cafeNormal.count     // 4
    
    cafeCombining.count  // 4
    

    这两项都等于4。这是因为Swift将一个字符串视为一个grapheme集群的集合。聪明的读者也会注意到,这意味着找出一个字符串的长度需要一点时间,因为你需要遍历所有的字符来确定有多少个grapheme集群。你不能简单地从查看内存中字符串的大小来判断。

    注意:在上面的代码中,使用Unicode速记法编写了字符的音,就是在括号中使用十六进制的代码点。你可以使用这个简写来编写任何Unicode字符。我必须在这里用它来组合字符,因为没有办法在键盘上键入这个音调字符!

    但是,有一种方法可以访问字符串中的底层Unicode代码点。你可以通过字符串的unicodeScalars视图来完成此操作。视图本身也是一个集合。你可以这样做:

    cafeNormal.unicodeScalars.count     // 4
    
    cafeCombining.unicodeScalars.count  // 5
    

    正如你所看到的,在这种情况下,你看到与你所期望的不一样。

    你可以像这样遍历Unicode标量视图:

    for codePoint incafeCombining.unicodeScalars {
    
      print(codePoint.value)
    
    }
    

    这将按预期打印下列数字列表:

    99
    
    97
    
    102
    
    101
    
    769
    
    字符串索引

    正如你前面看到的,为获得某个字符(意思是grapheme集群)索引到一个字符串,并不像使用整数下标那样简单。这是因为Swift想让你了解更详细,从而语法会更加冗长。

    根据字符串索引进行操作,其索引为字符串。例如,你获得表示字符串开头的索引:

    let firstIndex = cafeCombining.startIndex

    如果你在playground上点击firstIndex,你会注意到它是string类型的。字符串的索引并不是整数。

    然后,你可以使用该值来获取该索引中的字符(grapheme集群),

    像这样:

    let firstChar = cafeCombining[firstIndex]
    

    在这种情况下,firstChar当然是“c”。这个值的类型是字符,一个字母集群。

    类似地,你可以像这样获得最后的grapheme集群:

    let lastIndex = cafeCombining.endIndex
    
    let lastChar = cafeCombining[lastIndex]
    

    但是如果你这样做,你会犯一个致命的错误:

      fatal error: Can't form a Characterfrom an empty String
    

    因为endIndex实际上是在字符串的末尾,获取最后一个字符
    你需要这样做:

    let lastIndex = cafeCombining.index(before: cafeCombining.endIndex)
    
    let lastChar = cafeCombining[lastIndex]
    

    先获取一个索引之前的索引,然后在该索引中获取字符。或者你也可以从第一个字符移动:

    let fourthIndex = cafeCombining.index(cafeCombining.startIndex, offsetBy:
    3)
    
    let fourthChar = cafeCombining[fourthIndex]
    

    在这种情况下第四个字符是é。

    但正如你所知,这个例子中的é是由多个代码点组成的。你可以通过unicodeScalars视图,以同样的方式访问字符类型上的这些代码点。所以你可以这样做:

    fourthChar.unicodeScalars.count // 2
    
    fourthChar.unicodeScalars.forEach { codePoint in
    
      print(codePoint.value)
    
    }
    

    这一次,你将使用forEach函数遍历Unicode标量视图。count是2,按照预期,循环输出:

    101

    769

    相等的组合字符

    组合字符使字符串的相等比较变得更复杂。例如,思考café́这个词,一旦使用单一é字符,和使用组合字符,如下所示:

    QQ20180427-175918@2x.png

    这两个字符串在逻辑上是相等的。当它们在屏幕上打印时,它们使用相同的符号,看起来完全一样。但它们在电脑中以不同的方式表现出来。许多编程语言都认为这些字符串是不相等的,因为这些语言的工作方式是逐个地比较代码。然而,Swift认为这些字符串在默认情况下是相等的。让我们来看看它的作用:

    let equal= cafeNormal == cafeCombining
    

    在这种情况下,equal是真,因为这两个字符串在逻辑上是相同的。

    Swift的字符串比较使用了一种称为规范化的技术。在检查相等之前,Swift将两个字符串规范化,这意味着它们被转换为使用相同的特殊字符表示。

    不管用哪种方式进行规范化——使用单个字符还是使用组合字符——只要两个字符串都转换为相同的样式就行了。一旦规范化完成,Swift可以比较单个字符来检查是否相等。

    相同的规范化可以计算字符串长度,前面café和组合字符串的长度就是相等的。

    相关文章

      网友评论

          本文标题:字符串(一)

          本文链接:https://www.haomeiwen.com/subject/addilftx.html