Учитывая, что смешанные акцентированные и нормальные символы в строке не работают в Java при поиске - PullRequest
0 голосов
/ 16 октября 2018
String text = "Cámélan discovered ônte red aleŕt \n Como se extingue la deuda";

Если я введу ввод Ca, он должен выделяться из заданной строки Cá, но он не выделяется.

Ниже я попробовал.

 Pattern mPattern; 
  String filterTerm; //this is the input which I give from input filter. Say for eg: Ca
   String regex = createFilterRegex(filterTerm);
        mPattern = Pattern.compile(regex);

 private String createFilterRegex(String filterTerm) {
        filterTerm = Normalizer.normalize(filterTerm, Normalizer.Form.NFD);
       filterTerm = filterTerm.replaceAll("[\\p{InCombiningDiacriticalMarks}]", "");
        return filterTerm;
    }

public Pattern getPattern() {
        return mPattern;
    }

В другом классе

private SpannableStringBuilder createHighlightedString(String nodeText, int highlightColor) { //nodeText is the entire list displaying. 
        SpannableStringBuilder returnValue = new SpannableStringBuilder(nodeText);
        String lowercaseNodeText = nodeText;
        Matcher matcher = mFilter.getPattern().matcher((createFilterRegex(lowercaseNodeText)));
        while (matcher.find()) {
            returnValue.setSpan(new ForegroundColorSpan(highlightColor), matcher.start(0),
                    matcher.end(0), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
        }

        return returnValue;
    }

viewHolder.mTextView.setText (createHighlightedString ((node.getText ()),mHighlightColor));

Но то, что я получаю как:

Если я набираю один алфавит o в одиночку, это выделяется цветом, но если я передаю более двух алфавитов, например, для: Ca, этоне выделение и отображение.Я не мог понять, какую ошибку я делаю.

Но если вы посмотрите WhatsApp.это было достигнуто.

Я набрал Co, он распознает и выделяет акцентированные символы в предложении.

enter image description here

Ответы [ 3 ]

0 голосов
/ 25 октября 2018

Я не программист на Java, так что здесь просто базовое решение для регулярных выражений.

Если вы можете Нормализовать строку с ее декомпозицией формой
предположить, что это

String sSourceTargetDecom = Normalizer.normalize(sourcetarget, Normalizer.Form.NFD);,

это должно превратить что-то вроде 0000C1 Á LATIN CAPITAL LETTER A WITH ACUTE
в два символа A и 000301 ́ COMBINING ACUTE ACCENT.

Вы можете получить большинство комбинирующих символов из блоков, используя

[\p{Block=Combining_Diacritical_Marks}\p{Block=Combining_Diacritical_Marks_Extended}\p{Block=Combining_Diacritical_Marks_For_Symbols}\p{Block=Combining_Diacritical_Marks_Supplement}\p{Block=Combining_Half_Marks}]  

, который имеет шестнадцатеричный диапазон

[\x{300}-\x{36f}\x{1ab0}-\x{1aff}\x{1dc0}-\x{1dff}\x{20d0}-\x{20ff}\x{fe20}-\x{fe2f}]  

Оказывается, что большинство комбинирующих меток относительнобазовая латиница, которая может быть разложена на
, находится в диапазоне [\x{300}-\x{36f}].

Вы можете разложить и исходную цель и строку поиска ввода.


Затем создать регулярное выражение из строки поиска ввода. Введите [\x{300}-\x{36f}]? после каждой основной буквы латинского алфавита.

String regex = sSearch.replaceAll("([a-zA-Z])[\\x{300}-\\x{36f}]?", "\\1[\\x{300}-\\x{36f}]?");

(не уверен, что Java использует для обозначения кодовой точки в своем регулярном выражении, возможно, должно быть \u{DD}

Затем используйте регулярное выражение в строке sSourceTargetDecom , он будет соответствовать базовому латинскому языку как отдельному, и / или с дополнительным кодом объединения.

0 голосов
/ 26 октября 2018

Как вы сказали,

String text = "Camélan обнаружил, что все в порядке \ n Como se extingue la deuda";

Поэтому, когда вы даете первый ввод, получите этот первый символ и сравните,

Например: если вы дадите Ca, то

if (StringUtils.isNotEmpty(substring)) { //this is the search text
substring=substring.substring(0,1); //now you get C alone.

}

То, что вы наберете, будет отображаться с помощью фильтрации первого символа.Теперь

 SpannableString builder = higlightString((yourContent.getText()), mHighlightColor);
    viewHolder.mTextView.setText(builder);




private SpannableString higlightString(String entireContent, int highlightColor) {
            SpannableString returnValue = new SpannableString(entireContent);

            String lowercaseNodeText = entireContent;
        try {
            Matcher matcher = mFilter.getPattern().matcher(((diacritical(lowercaseNodeText.toLowerCase()))));
            while (matcher.find()) {
                returnValue.setSpan(new ForegroundColorSpan(highlightColor), matcher.start(0),
                        matcher.end(0), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }

            return returnValue;

    }



 private String diacritical(String original) {
       String removed=null;
           String decomposed = Normalizer.normalize(original, Normalizer.Form.NFD);
           removed = decomposed.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
       return removed;
   }

Контрольный пример:

Когда вы вводите Ca, он переходит ко всему тексту, отображая все содержимое C, получает все данные и отфильтровывает, нормализуя содержимое и егосовпадает с акцентированными символами и отображается при помощи выделения.

0 голосов
/ 16 октября 2018

Вы уже получили:

private String convertToBasicLatin(String text) {
    return Normalizer.normalize(text, Normalizer.Form.NFD)
        .replaceAll("\\p{M}", "").replaceAll("\\R", "\n");
}

Для того, чтобы один базовый латинский символ без акцента совпадал один Unicode-кодовая точка буквы с акцентом, необходимо нормализоватьв составленную форму:

private String convertToComposedCodePoints(String text) {
    return Normalizer.normalize(text, Normalizer.Form.NFC).replaceAll("\\R", "\n");
}

В целом можно предположить, что кодовая точка Unicode тоже имеет длину 1 символ.

  • Поискключ использует convertToBasicLatin (искомый)
  • содержимое текстового представления использует convertToComposedCodePoints (content)
  • текстовое содержимое для сопоставления использует convertToBasicLatin (content)

теперь индекс соответствияположения start и end являются правильными.Я явно нормализовал окончания строк (регулярное выражение \R), например \r\n или \u0085, до одного \n.Нельзя нормализовать строчные / прописные буквы, так как число символов может различаться: немецкая строчная ß соответствует прописной SS.

String sought = ...;
String content = ...;

sought = convertToBasicLatin(sought);
String latinContent = convertToBasicLatin(content);
String composedContent = convertToComposedUnicode(content);

Matcher m = Pattern.compile(sought, Pattern.CASE_INSENSITIVE
        | Pattern.UNICODE_CASE | Pattern.UNICODE_CHARACTER_CLASS
        | Pattern.UNIX_LINES)
    .matcher(latinContent);
while (m.find()) {
    ... // One can apply `m.start()` and `m.end()` to composedContent of the view too.
}
...