1. ホーム
  2. string

[解決済み] 文字列の文字数を取得する方法

2022-04-22 08:59:28

質問

Go で文字列の文字数を取得するには?

例えば、文字列 "hello" を返すべきであり、このメソッドは 5 . 私はそれを見た len(str) はバイト数を返します。 であって は文字数なので len("£") は1ではなく2を返します。これは£がUTF-8では2バイトでエンコードされているからです。

どのように解決するのですか?

を試してみてください。 RuneCountInString をutf8パッケージからダウンロードしてください。

p に含まれるルーンの数を返します。

に示されているように、その このスクリプト の長さは6(中国語表記:quot;World")かもしれませんが、ルーン数は2です。

package main
    
import "fmt"
import "unicode/utf8"
    
func main() {
    fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}

フローズン が追加されます。 コメント欄 :

実際には、以下のようなことが可能です。 len() をタイプキャストするだけでルーンを超えることができます。

len([]rune("世界")) を印刷します。 2 . 少なくともGo 1.3では。


そして CL 108985 (2018年5月、Go 1.11用)。 len([]rune(string)) が最適化されるようになりました。(修正内容 課題24923 )

コンパイラが検出する len([]rune(string)) のパターンに自動的に置き換えられ、for r := range s の呼び出しに置き換わります。

<ブロッククオート

文字列中のルーン数を数えるランタイム関数を新たに追加した。 コンパイラがパターンを検出するように修正 len([]rune(string)) に置き換え、新しいルーン数カウント実行関数で置き換えます。

RuneCount/lenruneslice/ASCII        27.8ns ± 2%  14.5ns ± 3%  -47.70%
RuneCount/lenruneslice/Japanese     126ns ± 2%   60  ns ± 2%  -52.03%
RuneCount/lenruneslice/MixedLength  104ns ± 2%   50  ns ± 1%  -51.71%


シュテファン・シュタイガー は、ブログ記事「"」を指します。 Goにおけるテキストの正規化 "

<ブロッククオート

キャラクターとは何ですか?

<ブロッククオート

で紹介されていたように 文字列のブログ記事 , キャラクターは複数のルーンにまたがることができる .

例えば、' e 'と'◌́◌'(アキュート"◌̀)が結合して'é'(" e\u0301 NFDでは")。 この2つのルーンは合わせて1つの文字になります .

キャラクターの定義は、用途によって異なる場合があります。

については 正規化 と定義することにします。

  • スターターから始まるルーンの列。
  • 他のルーンを修正したり、逆に結合したりしないルーン。
  • の後に、空白で始まる可能性のある非スターター、つまり、そうなるルーン(通常はアクセント)が続く。

正規化アルゴリズムは、一度に一文字ずつ処理します。

そのパッケージと Iter タイプ の場合、実際の文字数は、"character" となります。

package main
    
import "fmt"
import "golang.org/x/text/unicode/norm"
    
func main() {
    var ia norm.Iter
    ia.InitString(norm.NFKD, "école")
    nc := 0
    for !ia.Done() {
        nc = nc + 1
        ia.Next()
    }
    fmt.Printf("Number of chars: %d\n", nc)
}

ここで、これは ユニコード正規化形式 NFKD "Compatibility Decomposition"。


オリバー 's 答え を指します。 ユニコード・テキスト・セグメンテーション は、ユーザーが認識する文字、単語、文といった特定の重要なテキスト要素間のデフォルトの境界を確実に決定する唯一の方法であると考えられています。

のような外部ライブラリが必要です。 リボ/ユニセグ を行うものである。 ユニコード・テキスト・セグメンテーション .

これで実際にカウントされるのは " です。 書記素 クラスター 複数のコードポイントが組み合わされて、ユーザーが認識する1つの文字になることがあります。

package uniseg
    
import (
    "fmt"
    
    "github.com/rivo/uniseg"
)
    
func main() {
    gr := uniseg.NewGraphemes("????????!")
    for gr.Next() {
        fmt.Printf("%x ", gr.Runes())
    }
    // Output: [1f44d 1f3fc] [21]
}

ルーン文字(ユニコードコードポイント)が3つあるにもかかわらず、2つの書記素を持つ。

他の例は"で見ることができます。 GOで文字列を操作して反転させるには? "

は単独で1つの書記素ですが、そこから ユニコードからコードポイントへの変換 4つのルーン