質問

GOの文字列の文字数を取得できますか?

たとえば、文字列"hello"を持っている場合、メソッドは5を返します。len(str)がBytes の数を返し、の数を返しているため、len("£")は1文字の代わりに2を返します。

役に立ちましたか?

解決

RuneCountInString を試すことができます。

は、p の実行数を返します

このスクリプト: "World"の長さが6になる可能性があります。中国語で書かれたとき:「世界」)しかし、そのルーン数は2:

package main

import "fmt"
import "unicode/utf8"

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

Phrozen 追加コメント

実際には、鋳造のタイプで走行中のlen()を実行できます。
len([]rune("世界"))2を印刷します。 GO 1.3のレートで。


CL 108985 (2018年5月、GO 1.11) 、len([]rune(string))が最適化されました。 (修正問題24923

コンパイラは、len([]rune(string))パターンを自動的に検出し、それをR:=範囲の呼び出しに置き換えます。

文字列内の実行数をカウントするための新しいランタイム関数を追加します。 コンパイラを変更してPattern len([]rune(string))を検出します そしてそれを新しいRuneカウントランタイム関数に置き換えます。

RuneCount/lenruneslice/ASCII                  27.8ns ± 2%  14.5ns ± 3%  -47.70%  (p=0.000 n=10+10)
RuneCount/lenruneslice/Japanese                126ns ± 2%    60ns ± 2%  -52.03%  (p=0.000 n=10+10)
RuneCount/lenruneslice/MixedLength             104ns ± 2%    50ns ± 1%  -51.71%  (p=0.000 n=10+9)
.


Stefan Steiger ブログの投稿を指しています " GO " のテキストの正規化

文字とは何ですか?

文字列ブログ投稿文字は複数のルーンにまたがることができます
たとえば、 'e'と '◌◌'(Acute "\ U0301")は組み合わせることができ、「é」(「e\u0301」)を作成できます(NFD)。 一緒にこれら2つのルーンは1文字です。

キャラクタの定義はアプリケーションによって異なります。
正規化 私たちは次のように定義します。

他のヒント

Stringを[] Runeにlen([]rune(YOUR_STRING))として変換することによって、パッケージなしでルーンの数を取得する方法があります。

package main

import "fmt"

func main() {
    russian := "Спутник и погром"
    english := "Sputnik & pogrom"

    fmt.Println("count of bytes:",
        len(russian),
        len(english))

    fmt.Println("count of runes:",
        len([]rune(russian)),
        len([]rune(english)))

}
.

バイト数30 16

ルーンの数16 16

は、「文字」が何であるかの定義に大きく依存します。「Runeが文字に等しい」があなたの仕事のために問題ない場合(一般的にはそうではありません)、それからvoncによる答えはあなたに最適です。それ以外の場合は、Unicode文字列内の実行数が興味深い値である状況がいくつかあると注意すべきです。そしてそれらの状況でさえも、可能であれば、可能であれば、弦を「横断する」と弦を「横断する」と推測されると、UTF-8デコード努力を倍増させないように処理されます。

私はこれまでに提供された答えのどれもあなたが期待されるようにあなたに与えられた答えのどれも、特にあなたがEmojisを扱うとき(しかし、タイ、韓国語、またはアラビア語のようないくつかの言語)をあなたに与えることを指摘するべきです。 VONCの提案は次のものを出力します。

fmt.Println(utf8.RuneCountInString("🏳️‍🌈🇩🇪")) // Outputs "6".
fmt.Println(len([]rune("🏳️‍🌈🇩🇪"))) // Outputs "6".
.

これらのメソッドはUnicodeコードポイントのみを数えるだけです。複数のコードポイントで構成できる文字はたくさんあります。 正規化パッケージ

var ia norm.Iter
ia.InitString(norm.NFKD, "🏳️‍🌈🇩🇪")
nc := 0
for !ia.Done() {
    nc = nc + 1
    ia.Next()
}
fmt.Println(nc) // Outputs "6".
.

正規化は文字をカウント文字と同じではなく、多くの文字は1コード点と同等のものに正規化することはできません。

Masakielasticの答えは近くになりますが、修飾子を処理するだけです(Rainbowフラグはそれ自身としてカウントされていない修飾子を含みます)。コードポイント):

fmt.Println(GraphemeCountInString("🏳️‍🌈🇩🇪"))  // Outputs "5".
fmt.Println(GraphemeCountInString2("🏳️‍🌈🇩🇪")) // Outputs "5".
.

Unicode文字列を(ユーザー認識された)文字、すなわちGraphemeクラスタに分割する正しい方法は、 Unicode Standard Annex#29 。規則は、セクション3.1.1 セクション3.1.1で見つけることができます。 github.com/rivo/uniseg パッケージはこれらの規則を実装しているので、正しい文字数を決定できます。文字列:

fmt.Println(uniseg.GraphemeClusterCount("🏳️‍🌈🇩🇪")) // Outputs "2".
.

文字列の長さを取得する方法はいくつかあります:

package main

import (
    "bytes"
    "fmt"
    "strings"
    "unicode/utf8"
)

func main() {
    b := "这是个测试"
    len1 := len([]rune(b))
    len2 := bytes.Count([]byte(b), nil) -1
    len3 := strings.Count(b, "") - 1
    len4 := utf8.RuneCountInString(b)
    fmt.Println(len1)
    fmt.Println(len2)
    fmt.Println(len3)
    fmt.Println(len4)

}

.

正規化を少し高速にするために作りようとしました:

    en, _ = glyphSmart(data)

    func glyphSmart(text string) (int, int) {
        gc := 0
        dummy := 0
        for ind, _ := range text {
            gc++
            dummy = ind
        }
        dummy = 0
        return gc, dummy
    }
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top