web-dev-qa-db-ja.com

キャラクターのUnicodeコードポイントを取得するにはどうすればよいですか?

最初にCharacterに変換せずに、特定のStringのUnicodeコードポイントを抽出するにはどうすればよいですか。私は次のものを使用できることを知っています:

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

しかし、Swiftの標準ライブラリだけを使用してこれを達成するためのより直接的な方法があるはずです。言語ガイドのセクション "文字の操作" および "ユニコード" は、Stringを直接操作せずに、Character内の文字の繰り返しについてのみ説明します。 ] _s。

46
nathan

ドキュメントで収集できるものから、コンテキストを提供するため、CharacterからString値を取得することを望んでいます。これはCharacterがUTF8、UTF16、または21ビットコードポイント(スカラー)でエンコードされていますか?

Swift=フレームワークでCharacterがどのように定義されているかを見ると、実際にはenum値です。これはおそらく、 String.utf8String.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の構文上の砂糖がすぐに拡張されると確信しています。

31
Erik

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 "한"

文字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
}

追加の例

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

18
SLN

問題は、CharacterがUnicodeコードポイントを表していないことだと思います。これは、複数のコードポイントで構成される「Unicode書記素クラスター」を表します。

代わりに、UnicodeScalarはUnicodeコードポイントを表します。

7
newacct

私はあなたに同意します。キャラクターから直接コードを取得する方法があるはずです。しかし、私が提供できるのは速記だけです:

let ch: Character = "A"
for code in String(ch).utf8 { println(code) }
6
evpozdniakov

やってみました:

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文字のみである場合もあります。

0
Binarian

#1。 Unicode.Scalarvalueプロパティを使用する

Swift 5、Unicode.Scalarには、次の宣言を持つ value プロパティがあります。

Unicodeスカラーの数値表現。

var value: UInt32 { get }

次のPlaygroundサンプルコードは、unicodeScalarsCharacterプロパティを反復処理し、それを構成する各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
 */

#2。 CharacterasciiValueプロパティを使用する

本当に欲しいのが文字のASCIIエンコーディング値を取得することである場合、CharacterasciiValue を使用できます。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
 */
0
Imanou Petit