最初にCharacter
に変換せずに、特定のString
のUnicodeコードポイントを抽出するにはどうすればよいですか。私は次のものを使用できることを知っています:
let ch: Character = "A"
let s = String(ch).unicodeScalars
s[s.startIndex].value // returns 65
しかし、Swiftの標準ライブラリだけを使用してこれを達成するためのより直接的な方法があるはずです。言語ガイドのセクション "文字の操作" および "ユニコード" は、String
を直接操作せずに、Character
内の文字の繰り返しについてのみ説明します。 ] _s。
ドキュメントで収集できるものから、コンテキストを提供するため、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の構文上の砂糖がすぐに拡張されると確信しています。
Unicodeについて誤解があると思います。 Unicode自体は [〜#〜] not [〜#〜] エンコーディングであり、しない書記素クラスター(または「文字「人間の読書の観点から」あらゆる種類のバイナリシーケンスに。 Unicodeは、地球上のすべての言語で使用されるすべての書記素クラスターを収集する大きなテーブルです(非公式にはクリンゴンも含まれます)。これらの書記素クラスタは、コードポイント(Swiftの21ビット数、U + D800のように見える)によって編成およびインデックス付けされます。コードポイントを使用すると、大きなUnicodeテーブルで探している文字の場所を見つけることができます。
一方、UTF8、UTF16、UTF32と呼ばれるプロトコルは実際にはエンコーディングです。はい、Unicode文字をバイナリシーケンスにエンコードする方法は複数あります。どのプロトコルを使用するかは、作業しているプロジェクトによって異なりますが、ほとんどのWebページはUTF-8でエンコードされます(実際に確認できます)。
コンセプト1: Unicodeポイントは、 Unicodeスカラーと呼ばれます。
Unicodeスカラーは、U + 0000からU + D7FFまで、またはU + E000からU + 10FFFFまでの範囲のUnicodeコードポイントです。 Unicodeスカラーには、Unicodeサロゲートペアコードポイントは含まれません。これは、U + D800からU + DFFFまでの範囲のコードポイントです。
コンセプト2: Code Unit は、エンコーディングの抽象表現です。
次のコードスニペットを検討してください
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進数(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)")
Summary : Code Points 、別名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
問題は、Character
がUnicodeコードポイントを表していないことだと思います。これは、複数のコードポイントで構成される「Unicode書記素クラスター」を表します。
代わりに、UnicodeScalar
はUnicodeコードポイントを表します。
私はあなたに同意します。キャラクターから直接コードを取得する方法があるはずです。しかし、私が提供できるのは速記だけです:
let ch: Character = "A"
for code in String(ch).utf8 { println(code) }
やってみました:
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]
また、文字列内の1文字のみである場合もあります。
Unicode.Scalar
のvalue
プロパティを使用するSwift 5、Unicode.Scalar
には、次の宣言を持つ value
プロパティがあります。
Unicodeスカラーの数値表現。
var value: UInt32 { get }
次のPlaygroundサンプルコードは、unicodeScalars
のCharacter
プロパティを反復処理し、それを構成する各Unicodeスカラーの値を出力する方法を示しています。
let character: Character = "A"
for scalar in character.unicodeScalars {
print(scalar.value)
}
/*
prints: 65
*/
別の方法として、Character
の最初のUnicodeスカラーの値のみを出力する場合は、以下のサンプルコードを使用できます。
let character: Character = "A"
let scalars = character.unicodeScalars
let firstScalar = scalars[scalars.startIndex]
print(firstScalar.value)
/*
prints: 65
*/
Character
のasciiValue
プロパティを使用する本当に欲しいのが文字のASCIIエンコーディング値を取得することである場合、Character
の asciiValue
を使用できます。asciiValue
には次の宣言があります。
ASCIIの場合、このCharacterのASCII encoding値を返します。
var asciiValue: UInt8? { get }
以下のPlaygroundサンプルコードは、asciiValue
の使用方法を示しています。
let character: Character = "A"
print(String(describing: character.asciiValue))
/*
prints: Optional(65)
*/
let character: Character = "П"
print(String(describing: character.asciiValue))
/*
prints: nil
*/