Подтвердить что ты не робот

Как получить обратную строку (без юникода)

Предположим, мы хотим вернуть следующую строку "áe".

Юникод для этого - "\ u0061\u0301\u0065".

Наивный aproach обращения к нему будет char на char

private static String reverseStringNaive(String s) {
    char[] characters = new char[s.length()];
    for (int i = s.length() - 1; i >= 0; i--) {
        int j = s.length() - i - 1;
        characters[j] = s.charAt(i); 
    }
    return new String(characters);
}

который дает нам "éa" (\ u0065\u0301\u0061), когда мы надеемся получить "eá" (\ u0065\u0061\u0301). Акцентный акцент "должен совпадать с" а ", а не" е".

Следующий код дает мне ожидаемый результат для этой строки:

private static String reverseString(String s) {
    char[] characters = new char[s.length()];
    for (int i = s.length() - 1; i >= 0; i--) {
        int j = s.length() - i - 1;
        if (Character.isLetterOrDigit(s.charAt(i)) || Character.isISOControl(s.charAt(i))) {
            characters[j] = s.charAt(i); 
        } else {
            characters[j] = s.charAt(i-1);
            characters[j+1] = s.charAt(i);
            i--;
        }
    }
    return new String(characters);
}

Я проверяю, есть ли каждый символ Letter, Digit или ISO Control. Если нет, я предполагаю, что он должен совпадать с предыдущим символом.

Вопрос в том, есть ли другие вещи, о которых я должен проверить или беспокоиться? Является ли мой aproach еще наивным?

4b9b3361

Ответ 1

Ваша проблема также может быть решена путем преобразования строки в каноническую форму разложения NFC. В принципе, класс java.text.Normalizer может использоваться для объединения акцентов и других комбинаций символов с их базовыми символами, чтобы вы могли правильно отменить.

Все эти другие идеи (String.reverse(), StringBuffer.reverse()) будут правильно менять символы в вашем буфере, но если вы начнете с разложенных символов, вы можете не получить то, что ожидаете:).

В некоторых "формах разложения" символы акцента хранятся отдельно от их базовых форм (в виде отдельных символов), но в "комбинированной" форме они не являются. Таким образом, в одной форме "áe" хранится как три символа, а в другой, объединенной форме, как два.

Однако такая нормализация недостаточна для обработки других комбинаций символов и не может содержать символы в астральных плоскостях Юникода, которые хранятся в виде двух символов (или более?) в Java.

Благодаря tchrist для указания поддержки ICU сегментации текста, включая расширенные кластеры grapheme, такие как те, которые указаны в комментариях ниже (см. virama). Этот ресурс, по-видимому, является авторитетным источником информации о подобных вещах.