webentwicklung-frage-antwort-db.com.de

Bei gemischten Akzenten und normalen Zeichen in der Zeichenfolge, die bei der Suche nicht in Java ausgeführt werden

String text = "Cámélan discovered ônte red aleŕt \n Como se extingue la deuda";

Wenn ich den Wert Ca eingebe, sollte er von der angegebenen Zeichenfolge Cá hervorgehoben werden, er wird jedoch nicht hervorgehoben. 

Unten habe ich versucht.

 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;
    }

In einer anderen Klasse

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));

Aber was bekomme ich als Ausgabe, 

Wenn ich ein einzelnes Alphabet o eingebe, wird dies hervorgehoben, aber wenn ich mehr als zwei Alphabete übergebe, sagen Sie zum Beispiel: Ca, es wird nicht hervorgehoben und angezeigt. Ich konnte nicht herausfinden, welchen Fehler ich mache. 

Aber wenn Sie WhatsApp suchen. es wurde erreicht. 

Ich habe Co getippt, es werden akzentuierte Zeichen im Satz erkannt und hervorgehoben. 

 enter image description here

9
Star

Wie du gesagt hast, 

String text = "Cámélan hat ein rotes Bier gefunden\n Como se extingue la deuda";

Wenn Sie also die erste Eingabe machen, erhalten Sie das erste Zeichen und vergleichen es. 

ZB: Wenn Sie Ca geben, dann

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

}

Was auch immer Sie eingeben, es wird angezeigt, indem Sie das erste Zeichen filtern. Jetzt 

 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;
   }

Testfall: 

Wenn Sie den Wert Ca eingeben, wird der gesamte Text angezeigt, indem der gesamte C-Inhalt angezeigt wird. Holen Sie alle Daten heraus und filtern Sie den Inhalt aus, indem Sie den Inhalt normalisieren. Er stimmt auch mit Akzentzeichen überein und wird durch Hervorhebung angezeigt.

2
Shadow

Du hast schon:

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

Um one nicht akzentuierte grundlegende lateinische Char-Übereinstimmungen one Unicode-Codepunkt eines akzentuierten Buchstabens zu haben, sollte Die auf die zusammengestellte form normalisiert werden:

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

Im Allgemeinen könnte man davon ausgehen, dass der Unicode-Codepunkt ebenfalls 1 Zeichen lang ist.

  • Der Suchschlüssel verwendet convertToBasicLatin (gesucht)
  • Der Inhalt der Textansicht verwendet convertToComposedCodePoints (Inhalt).
  • Der Text für den Abgleich verwendet convertToBasicLatin (content)

Nun sind die Indexpositionen des Matchers start und end korrekt. Ich habe explizit Zeilenenden (Regex \R) wie \r\n oder \u0085 auf einen einzelnen \n. Normalisiert Die Anzahl der Zeichen kann variieren: Deutscher ß entspricht Großbuchstaben 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.
}
1
Joop Eggen

Ich bin kein Java-Programmierer, also hier nur eine einfache Raw-Regex-Lösung. 

Wenn Sie normalisieren können die Zeichenfolge mit ihrer Zerlegung Form
nehme an, es ist das 

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

das sollte etwas wie 0000C1 Á LATIN CAPITAL LETTER A WITH ACUTE werden
in zwei Zeichen A und 000301 ́ COMBINING ACUTE ACCENT

Sie können die meisten kombinierten Zeichen aus Blöcken mit erhalten 

[\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}]  

die einen Hex-Bereich von hat 

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

Es stellt sich heraus, dass die meisten Kombinationsmerkmale relativ zum Basislatein sind
zerlegt liegt im [\x{300}-\x{36f}]-Bereich. 

Sie können beide das Quellziel und den Eingabesuchstring zerlegen.


Erstellen Sie dann aus dem eingegebenen Suchstring einen Regex. Inject [\x{300}-\x{36f}]? nach jedem lateinischen Buchstaben. 

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

(nicht sicher, was Java für die Codepunktzeichen-Notation in ihrer Regex verwendet, muss möglicherweise \u{DD} sein

Verwenden Sie dann den regulären Ausdruck für die Zeichenfolge sSourceTargetDecom , und der Grundlatein wird als eigenständige Einheit und/oder mit einem optionalen Kombinationscode angezeigt.

0
sln