Android 絵文字を含んだ文字数カウントをある程度正確にやる
文字数カウントなんて
String.codePointCount(o, maxLength)
すれば余裕だろガッハッハッハッハ!!!!!!
と思ってたんですが大きな間違いでした.........
何がどう間違いなのか
という形で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のページを確認してみる
たとえば、実装では、 「.」を解釈しながら、 \X を 拡張書記素クラスターに一致するものとして解釈できます。任意の単一のコードポイントと一致するものとして。\b{g} を拡張書記素クラスター境界に対するゼロ幅の一致として解釈し、\B{g} を その補数として解釈する可能性があります。
(翻訳文)
どうやら
"\\X"
でよさそう????
最終的に
こうなりました
fun String.countCharAndEmoji(): Int {
return Regex("\\X").findAll(this).count()
}
これで検証した限りではいけそうでした!!!
他にもっといい方法があれば教えて欲しいです。
参考記事
Discussion