🌟

Android 絵文字を含んだ文字数カウントをある程度正確にやる

2023/08/22に公開

文字数カウントなんて

String.codePointCount(o, maxLength)

すれば余裕だろガッハッハッハッハ!!!!!!

と思ってたんですが大きな間違いでした.........

何がどう間違いなのか

https://qiita.com/irgaly/items/7882b6a5dde5739c78d0

https://qiita.com/irgaly/items/5decdbf5ed89f9cf2c27

https://android.benigumo.com/20230529/kotlin-unicode/

https://news.mynavi.jp/article/20210907-1966765/

という形でUnicodeやら何やらで正確に文字数をカウントをすることが

非常に難しいことがわかりました

じゃあどうするか?

ChatGPTさんに聞いてみました

Kotlinを使ったAndroid開発で絵文字を含む文字列の文字数を正確にカウントするためには、codePointCount メソッドを使用するのは一般的には正しいアプローチですが、一部の絵文字が正しくカウントされない場合があります。これは、絵文字が1つのUnicodeコードポイントで表現されないことがあるためです。絵文字は複数のUnicodeコードポイントで構成されることがあり、その場合は単純に codePointCount メソッドだけでは正確な文字数を取得することが難しいです。

代わりに、Kotlinの CharacterIterator を使用して絵文字を含む文字列の文字数を正確にカウントする方法を以下に示します。

import java.text.BreakIterator

fun countEmojiCharacters(input: String): Int {
    val iterator = BreakIterator.getCharacterInstance()
    iterator.setText(input)

    var count = 0
    while (iterator.next() != BreakIterator.DONE) {
        val start = iterator.current()
        val end = iterator.next()

        val character = input.substring(start, end)
        if (character.isNotEmpty() && character.isEmoji()) {
            count++
        }
    }

    return count
}

fun String.isEmoji(): Boolean {
    val regex = Regex("\\p{Extended_Pictographic}")
    return this.matches(regex)
}

このコードは、絵文字を正確にカウントするために BreakIterator を使用しています。isEmoji 関数は正規表現を使って絵文字を判定しています。このコードは、絵文字が複数のUnicodeコードポイントで構成される場合でも正確な文字数を取得できるはずです。

注意: 絵文字のUnicodeサポートは継続的に進化しており、新しい絵文字やバージョンによっては正確なカウント方法が変わる可能性があります。最新の情報に基づいてコードを調整することをおすすめします。


なるほど

なんかいけそうな気がしますね。

Unicodeのページを確認してみる

http://www.unicode.org/reports/tr18/#RL2.2

たとえば、実装では、 「.」を解釈しながら、 \X を 拡張書記素クラスターに一致するものとして解釈できます。任意の単一のコードポイントと一致するものとして。\b{g} を拡張書記素クラスター境界に対するゼロ幅の一致として解釈し、\B{g} を その補数として解釈する可能性があります。
(翻訳文)

どうやら

"\\X"

でよさそう????

最終的に

こうなりました

fun String.countCharAndEmoji(): Int {
    return Regex("\\X").findAll(this).count()
}


これで検証した限りではいけそうでした!!!

他にもっといい方法があれば教えて欲しいです。

参考記事

https://qiita.com/irgaly/items/7882b6a5dde5739c78d0

https://qiita.com/irgaly/items/5decdbf5ed89f9cf2c27

https://android.benigumo.com/20230529/kotlin-unicode/

https://news.mynavi.jp/article/20210907-1966765/

http://www.unicode.org/reports/tr18/#RL2.2

Discussion