如何获取角色的Unicode代码点?

nat*_*han 47 unicode swift

如何在Character不先将其转换为String?的情况下提取给定的Unicode代码点?我知道我可以使用以下内容:

let ch: Character = "A"
let s = String(ch).unicodeScalars
s[s.startIndex].value // returns 65
Run Code Online (Sandbox Code Playgroud)

但似乎应该有一个更直接的方法来完成这个使用Swift的标准库.语言指南"使用字符""Unicode"部分仅讨论迭代a中的字符String,而不是直接使用Characters.

Eri*_*rik 32

根据我在文档中收集的内容,他们希望您Character从a 获取值,String因为它提供了上下文.这是Character用UTF8,UTF16还是21位代码点(标量)编码的?

如果你看看如何Character在Swift框架中定义a ,它实际上是一个enum值.这可能是由于做从各种表示String.utf8,String.utf16String.unicodeScalars.

看起来他们不希望你使用Character值,而是Strings你和程序员决定如何从String自身获取这些,允许编码被保留.

也就是说,如果你需要以简洁的方式获得代码点,我会建议像这样的扩展:

extension Character
{
    func unicodeScalarCodePoint() -> UInt32
    {
        let characterString = String(self)
        let scalars = characterString.unicodeScalars

        return scalars[scalars.startIndex].value
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

let char : Character = "A"
char.unicodeScalarCodePoint()
Run Code Online (Sandbox Code Playgroud)

总之,当您考虑所有可能性时,字符串和字符编码是一件棘手的事情.为了能够表达每种可能性,他们采用了这种方案.

还要记住这是一个1.0版本,我相信他们很快就会扩展Swift的语法糖.

  • Beta4增加了全角色支持,A角色现在可以拥有完整的字形群集.请参阅:Ole Begemann的[Strings in Swift](http://oleb.net/blog/2014/07/swift-strings/) (4认同)
  • `Character`值肯定有足够的上下文来确定代码点:例如,它们可以打印并连接到`String`s和其他`Character`s,并且通过`String`的解决方案不会起作用.我是否正确地断定标准库中缺少这个? (3认同)
  • @Erik_at_Digit您的代码不再起作用请查看此问题http://stackoverflow.com/questions/30334653/strange-behavior-with-swift-compiler在其他情况下您必须返回`UInt32`而不是`Int` (2认同)

SLN*_*SLN 18

我认为对Unicode有一些误解.Unicode本身不是一种编码,它不会将任何字形集群(或人类阅读方面的"字符")转换为任何类型的二进制序列.Unicode只是一个大表,它收集地球上所有语言使用的所有字形簇(非正式地还包括克林贡语).这些字形簇由代码点组织和索引(swift中的21位数字,看起来像U + D800).您可以使用代码点在大型Unicode表中找到您要查找的字符的位置

同时,称为UTF8,UTF16,UTF32的协议实际上是编码.是的,有多种方法可以将Unicode字符编码为二进制序列.使用哪种协议取决于您正在使用的项目,但大多数网页都是由UTF-8编码的(您现在可以实际检查它).

概念1: Unicode点在Swift中称为Unicode标量

Unicode标量是U + 0000到U + D7FF(含)或U + E000到U + 10FFFF(含)的任何Unicode代码点.Unicode标量不包括Unicode代理对代码点,它们是U + D800到U + DFFF范围内的代码点.

概念2:代码单元是编码的抽象表示.

请考虑以下代码段

let theCat = "Cat!"

for char in theCat.utf8 {
    print("\(char) ", terminator: "") //Code Unit of each grapheme cluster for the UFT8 encoding
}
print("")
for char in theCat.utf8 {
    print("\(String(char, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF8 encoding
}
print("")


for char in theCat.utf16 {
    print("\(char) ", terminator: "") //Code Unit of each grapheme cluster for the UFT-16 encoding
}
print("")
for char in theCat.utf16 {
    print("\(String(char, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF-16 encoding
}
print("")

for char in theCat.unicodeScalars {
    print("\(char.value) ", terminator: "") //Code Unit of each grapheme cluster for the UFT-32 encoding
}
print("")
for char in theCat.unicodeScalars {
    print("\(String(char.value, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF-32 encoding
}
Run Code Online (Sandbox Code Playgroud)

抽象表示意味着:代码单元由基数为10的数字(十进制数)写入,它等于基数为2的编码(二进制序列).对机器进行编码,代码单元更适合人类,它比二进制序列更容易阅读.

概念3:字符可能具有不同的Unicode点.这取决于角色如何通过什么字形聚类来收缩(这就是为什么我在开始时从人类阅读方面"人物")

请考虑以下代码段

let precomposed: String = "\u{D55C}"
let decomposed: String = "\u{1112}\u{1161}\u{11AB}" 
print(precomposed.characters.count) // print "1"
print(decomposed.characters.count) // print "1" => Character != grapheme cluster
print(precomposed) //print "?"
print(decomposed) //print "?"
Run Code Online (Sandbox Code Playgroud)

的字符precomposeddecomposed在视觉上和语言相等,但是他们有不同的Unicode点和不同的代码单元,如果他们通过相同的编码协议编码的(见下面例子)

for preCha in precomposed.utf16 {
    print("\(preCha) ", terminator: "") //print 55357 56374 128054 54620
}

print("")

for deCha in decomposed.utf16 {
    print("\(deCha) ", terminator: "") //print 4370 4449 4523
}
Run Code Online (Sandbox Code Playgroud)

额外的例子

var word = "cafe"
print("the number of characters in \(word) is \(word.characters.count)")

word += "\u{301}"

print("the number of characters in \(word) is \(word.characters.count)")
Run Code Online (Sandbox Code Playgroud)

总结:Code Points,Aka是Unicode中字符的位置索引,与UTF-8,UTF-16和UTF-32编码方案无关.

进一步阅读:

http://www.joelonsoftware.com/articles/Unicode.html

http://kunststube.net/encoding/

https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html


new*_*cct 7

我认为问题在于它Character不代表Unicode代码点.它代表一个"Unicode字形集群",它可以包含多个代码点.

相反,UnicodeScalar表示Unicode代码点.

  • 我编辑了问题,使用"代码点"而不是"代码点".我写的时候大部分时间都在考虑代表单个代码点的字符,但这不是真正的问题 - "字符"仍然是Unicode标量的容器,你应该能够直接提取,即,没有先将其转换为`String`. (3认同)

evp*_*kov 6

我同意你的看法,应该有一种直接从角色获取代码的方法.但我能提供的只是一个简写:

let ch: Character = "A"
for code in String(ch).utf8 { println(code) }
Run Code Online (Sandbox Code Playgroud)