如何在不首先将其转换为Character
的情况下提取给定String
的Unicode代码点?我知道我可以使用以下内容:
let ch: Character = "A"
let s = String(ch).unicodeScalars
s[s.startIndex].value // returns 65
但似乎应该有一个更直接的方法来使用Swift的标准库来实现这一点。语言指南部分"Working with Characters"和"Unicode"仅讨论迭代String
中的字符,而不是直接使用Character
s。
答案 0 :(得分:31)
根据我在文档中收集的内容,他们希望您从Character
获取String
值,因为它提供了上下文。这个Character
是用UTF8,UTF16还是21位代码点(标量)编码的?
如果你看看如何在Swift框架中定义Character
,它实际上是enum
值。这可能是由于String.utf8
,String.utf16
和String.unicodeScalars
的各种表示而导致的。
他们似乎不希望您使用Character
值,而是使用Strings
,并且您作为程序员决定如何从String
本身获取这些值,从而允许保留编码
那就是说,如果你需要以简洁的方式获得代码点,我会建议像这样的扩展:
extension Character
{
func unicodeScalarCodePoint() -> UInt32
{
let characterString = String(self)
let scalars = characterString.unicodeScalars
return scalars[scalars.startIndex].value
}
}
然后你可以像这样使用它:
let char : Character = "A"
char.unicodeScalarCodePoint()
总之,当您考虑所有可能性时,字符串和字符编码是一件棘手的事情。为了能够表达每种可能性,他们采用了这种方案。
还记得这是一个1.0版本,我相信他们很快就会扩展Swift的语法糖。
答案 1 :(得分:17)
我认为对Unicode存在一些误解。 Unicode本身是 NOT 编码,不将任何字形集群(或人类阅读方面的“字符”)转换为任何类型的二进制序列。 Unicode只是一个大表,它收集地球上所有语言使用的所有字形簇(非正式地还包括克林贡语)。这些字形簇由代码点组织和索引(swift中的21位数字,看起来像U + D800)。您可以使用代码点
在大型Unicode表中找到您要查找的字符的位置同时,名为UTF8,UTF16,UTF32的协议实际上是编码。是的,有多种方法可以将Unicode字符编码为二进制序列。使用哪种协议取决于您正在使用的项目,但大多数网页都是由UTF-8编码的(您现在可以实际检查它)。
概念1:在Swift中将Unicode点称为 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
}
抽象表示意味着:代码单元由基数为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 "한"
字符precomposed
和decomposed
在视觉上和语言上相同,但如果它们使用相同的编码协议编码,则它们具有不同的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
}
额外示例
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)")
摘要:代码点,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
答案 2 :(得分:6)
我认为问题是Character
不代表Unicode代码点。它代表一个“Unicode字形集群”,它可以包含多个代码点。
相反,UnicodeScalar
表示Unicode代码点。
答案 3 :(得分:6)
我同意你的观点,应该有一种直接从角色获取代码的方法。但我能提供的只是一个简写:
let ch: Character = "A"
for code in String(ch).utf8 { println(code) }
答案 4 :(得分:0)
你试过了吗?
import Foundation
let characterString: String = "abc"
var numbers: [Int] = Array<Int>()
for character in characterString.utf8 {
let stringSegment: String = "\(character)"
let anInt: Int = stringSegment.toInt()!
numbers.append(anInt)
}
numbers
[97,98,99]
字符串中也可能只有一个字符。
答案 5 :(得分:0)
Unicode.Scalar
的{{1}}属性在Swift 5中,value
具有一个value
属性,该属性具有以下声明:
Unicode标量的数字表示形式。
Unicode.Scalar
下面的Playground示例代码演示如何遍历var value: UInt32 { get }
的{{1}}属性并打印组成它的每个Unicode标量的值:
unicodeScalars
或者,如果您只想打印Character
的第一个unicode标量的值,则可以使用下面的示例代码:
let character: Character = "A"
for scalar in character.unicodeScalars {
print(scalar.value)
}
/*
prints: 65
*/
Character
的{{1}}属性如果您真正想要的是获取字符的ASCII编码值,则可以使用let character: Character = "A"
let scalars = character.unicodeScalars
let firstScalar = scalars[scalars.startIndex]
print(firstScalar.value)
/*
prints: 65
*/
的{{3}}。 Character
具有以下声明:
如果是ASCII,则返回此字符的ASCII编码值。
asciiValue
下面的Playground示例代码显示了如何使用Character
:
asciiValue
var asciiValue: UInt8? { get }