Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get correct index of character in string by counting emojis only as one character

The problem on my android app is that when I count the length of a string with emojis in it, each emoji counts as two or more characters. I'm working on the android version of an app that has an iOS version. iOS counts each emoji as one character - when the index gets returned from the iOS app it assumes each emoji is counted as one.

"Hi i love 👻 @team"

I would like to get the index of @team, when the only information I have is the index given by iOS which is 13, on android this maybe 14 or even 15.

like image 293
HannahCarney Avatar asked Oct 24 '25 17:10

HannahCarney


1 Answers

This answer proposes to use java's Unicode support for code points.

An emoji symbol (grapheme) is a Unicode code point. Java internally also uses Unicode, but normally as (UTF-16) char a two-byte code, and an emoji has a code point with a Unicode number much higher. Hence java uses several chars. For a start with emojis.

But one can use code points in java. Java 8 has some extra help; not needed but I hope Android is already up to to some functionality.

Taking the length in code points:

int codePointsLength(String s) {
    int n = 0;
    for (int i = 0; i < s.length(); ) {
        int codePoint = s.codePointAt(i);
        i += Character.charCount(codePoint);
        ++n;
    }
    return n;
}

int codePointsLength(String s) {
    return (int) s.codePoints().count(); // Java 8.
}

Making a string from an emoji, using the Unicode code point:

final int RAISED_EYEBROW = 0x1f928; // U+1F928.
String s = new String(new int[] {RAISED_EYEBROW}, 0, 1);

Finding the position of the string indexed by code point:

int codePointIndexOf(String s, int codePoint) {
    int n = 0;
    for (int i = 0; i < s.length(); ) {
        int cp = s.codePointAt(i);
        if (cp == codePoint) {
            return n;
        }
        i += Character.charCount(cp);
        ++n;
    }
    return -1;
}

// Java 9 takeWhile.
int codePointIndexOf(String s, int codePoint) {
    int totalCount = (int) s.codePoints().count();
    int count = (int) s.codePoints().takeWhile(cp -> cp != codePoint).count();
    return count >= totalCount ? -1 : count;
}
like image 176
Joop Eggen Avatar answered Oct 26 '25 07:10

Joop Eggen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!