Как я могу получить код кода Unicode символа?
Как я могу извлечь кодовую точку Unicode для данного Character
без предварительного преобразования ее в String
? Я знаю, что могу использовать следующее:
let ch: Character = "A"
let s = String(ch).unicodeScalars
s[s.startIndex].value // returns 65
но кажется, что должен быть более прямой способ выполнить это, используя стандартную библиотеку Swift. Раздел "Руководство по языку" "Работа с символами" и "Unicode" обсуждать только итерации по символам в String
, не работая напрямую с Character
s.
Ответы
Ответ 1
Из того, что я могу собрать в документации, они хотят, чтобы вы получили значения Character
от String
, потому что это дает контекст. Является ли этот Character
закодированным с UTF8, UTF16 или 21-битными кодовыми точками (скалярами)?
Если вы посмотрите на то, как Character
определен в структуре Swift, это фактически значение 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.
Ответ 2
Я думаю, что есть некоторые недоразумения в отношении Unicode. Сам Unicode является НЕ кодировкой, не не преобразовывает кластеры графемы (или "символы" из уважения к чтению) в любую двоичную последовательность. Unicode - это просто большая таблица, которая собирает все кластеры графемы, используемые всеми языками на Земле (неофициально также включает в себя клингон). Эти кластеры grapheme организованы и индексируются кодовыми точками (21-битное число в swift и выглядит как U + D800). Вы можете найти, где персонаж, которого вы ищете в большой таблице Юникода, с помощью кодовых точек
Между тем, протокол UTF8, UTF16, UTF32 фактически кодирует. Да, существует несколько способов кодирования символов Юникода в двоичные последовательности. Использование протокола зависит от проекта, который вы работаете, но большая часть веб-страницы кодируется UTF-8 (вы можете проверить ее сейчас).
Концепция 1: Точка Unicode называется Unicode Scalar в Swift
Сканер Unicode представляет собой любую кодовую точку Unicode в диапазоне U + 0000 до U + D7FF включительно или U + E000 до U + 10FFFF включительно. Сканеры Unicode не включают в себя кодовые точки суррогатной пары Unicode, которые являются кодовыми точками в диапазоне U + D800 до U + DFFF включительно.
Концепция 2: Элемент Code - это абстрактное представление кодировки.
Рассмотрим следующий фрагмент кода
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
}
Абстрактное представление означает: блок кода записывается номером base-10 (десятичное число), равным кодировке base-2 (двоичная последовательность). Кодирование сделано для машин, Code Unit больше подходит для людей, его легко читать, чем двоичные последовательности.
Концепция 3: У символа могут быть разные юникодные точки. Это зависит от того, как персонаж заключен в какие кластеры графема (вот почему я сказал "Персонажи" от уважения к чтению людей в начале)
рассмотрим следующий фрагмент кода
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)")
Резюме: Кодовые точки, как индекс позиции символов в Юникоде, не имеет ничего общего с схемами кодирования 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
Ответ 3
Я согласен с вами, должен быть способ получить код непосредственно от персонажа. Но все, что я могу предложить, это сокращение:
let ch: Character = "A"
for code in String(ch).utf8 { println(code) }
Ответ 4
Я думаю, проблема в том, что Character
не представляет собой кодовую точку Unicode. Он представляет собой "Unicode grapheme cluster", который может состоять из нескольких кодовых точек.
Вместо этого UnicodeScalar
представляет собой кодовую точку Unicode.
Ответ 5
Вы пробовали:
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]
Он также может быть только одним символом в строке.