Domanda

Il problema è che, come sai, ci sono migliaia di caratteri in il grafico Unicode e voglio convertire tutti i caratteri simili in lettere che sono in alfabeto inglese.

Ad esempio qui ci sono alcune conversioni:

ҥ->H
Ѷ->V
Ȳ->Y
Ǭ->O
Ƈ->C
tђє Ŧค๓เℓy --> the Family
...

e ho visto che ci sono più di 20 versioni della lettera A / a. e non so come classificarli. Sembrano aghi nel pagliaio.

L'elenco completo dei caratteri unicode è disponibile all'indirizzo http: //www.ssec .wisc.edu / ~ tomw / java / unicode.html o http://unicode.org /charts/charindex.html . Prova a scorrere verso il basso e vedi le variazioni delle lettere.

Come posso convertire tutti questi con Java? Per favore aiutatemi :(

È stato utile?

Soluzione

Ripubblicazione del mio post da Come posso rimuovere i segni diacritici (accenti) da una stringa in .NET?

Questo metodo funziona bene in java (esclusivamente allo scopo di rimuovere segni diacritici noti anche come accenti) .

In pratica converte tutti i personaggi accentati nelle loro controparti deAccentate seguite dalla combinazione dei segni diacritici. Ora puoi usare una regex per eliminare i segni diacritici.

import java.text.Normalizer;
import java.util.regex.Pattern;

public String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); 
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}

Altri suggerimenti

Fa parte di Apache Commons Lang dalla ver. 3.0.

org.apache.commons.lang3.StringUtils.stripAccents("Añ");

restituisce An

Vedi anche http: //www.drillio. com / it / software-sviluppo / java / rimozione-accenti-segni diacritici-in-qualsiasi-language /

Tentativo di " convertirli tutti " è l'approccio sbagliato al problema.

In primo luogo, devi comprendere i limiti di ciò che stai cercando di fare. Come altri hanno sottolineato, i segni diacritici sono lì per una ragione: sono essenzialmente lettere uniche nell'alfabeto di quella lingua con il loro significato / suono, ecc .: rimuovere quei segni è lo stesso che sostituire le lettere casuali in una parola inglese. Questo è ancora prima di prendere in considerazione le lingue cirilliche e altri testi basati su script come l'arabo, che semplicemente non può essere "convertito". in inglese.

Se devi , per qualsiasi motivo, convertire i personaggi, l'unico modo sensato di affrontarlo per ridurre innanzitutto l'ambito dell'attività a portata di mano. Considera la fonte dell'input: se stai codificando un'applicazione per "il mondo occidentale" (per usare una frase buona come una qualsiasi), è improbabile che tu abbia mai bisogno di analizzare i caratteri arabi. Allo stesso modo, il set di caratteri Unicode contiene centinaia di simboli matematici e pittorici: non c'è modo (facile) per gli utenti di inserirli direttamente, quindi puoi presumere che possano essere ignorati.

Seguendo questi passaggi logici è possibile ridurre il numero di caratteri possibili per analizzare al punto in cui è possibile eseguire un'operazione di ricerca / sostituzione basata su dizionario. Diventa quindi una piccola quantità di lavoro leggermente noioso creando i dizionari e un compito banale per eseguire la sostituzione. Se la tua lingua supporta i caratteri Unicode nativi (come fa Java) e ottimizza correttamente le strutture statiche, tale ricerca e sostituzione tendono ad essere incredibilmente veloci.

Ciò deriva dall'esperienza di aver lavorato su un'applicazione richiesta per consentire agli utenti finali di cercare dati bibliografici che includessero caratteri diacritici. Le matrici di ricerca (come nel nostro caso) hanno richiesto forse 1 giorno uomo per produrre, per coprire tutti i segni diacritici per tutte le lingue dell'Europa occidentale.

Dalla codifica che trasforma "la Famiglia" in " t & # 1106; & # 1108; & # 358; & # 3588; & # 3667; & # 3648; & # 8467; y " è effettivamente casuale e non segue alcun algoritmo che può essere spiegato dalle informazioni dei punti di codice Unicode coinvolti, non esiste un modo generale per risolverlo algoritmicamente.

Dovrai costruire la mappatura dei caratteri Unicode in caratteri latini a cui assomigliano. Probabilmente potresti farlo con un po 'di machine learning intelligente sui glifi reali che rappresentano i punti di codice Unicode. Ma penso che lo sforzo per questo sarebbe maggiore della costruzione manuale di quella mappatura. Soprattutto se hai una buona quantità di esempi da cui puoi costruire la tua mappatura.

Per chiarire: alcune delle sostituzioni possono effettivamente essere risolte tramite i dati Unicode (come dimostrano le altre risposte), ma alcune lettere semplicemente non hanno alcuna associazione ragionevole con i caratteri latini a cui assomigliano.

Esempi:

  • " & # 1106; " (U + 0452 LETTERA PICCOLA LETTERA CYRILLIC) è più correlata a "d" rispetto a "h", ma viene utilizzato per rappresentare "h".
  • " & # 358; " (U + 0166 LETTERA DI CAPITALE LATINA T CON CORSA) è in qualche modo correlata a "T" (come suggerisce il nome) ma viene utilizzato per rappresentare " F " ;.
  • " & # 3588; " (U + 0E04 THAI CHARACTER KHO KHWAI) non è affatto correlato a nessun carattere latino e nel tuo esempio viene usato per rappresentare " a "

La richiesta originale ha già ricevuto risposta.

Tuttavia, sto pubblicando la risposta di seguito per coloro che potrebbero essere alla ricerca di un codice di traslitterazione generico per traslitterare qualsiasi set di caratteri in latino / inglese in Java.

Significato ingenuo di traslitterazione: La stringa tradotta nella sua forma / set di caratteri finale suona come la stringa nella sua forma originale. Se vogliamo traslitterare qualsiasi set di caratteri in latino (alfabeti inglesi), allora ICU4 (libreria ICU4J in Java) farà il lavoro.

Ecco lo snippet di codice in Java:

    import com.ibm.icu.text.Transliterator; //ICU4J library import

    public static String TRANSLITERATE_ID = "NFD; Any-Latin; NFC";
    public static String NORMALIZE_ID = "NFD; [:Nonspacing Mark:] Remove; NFC";

    /**
    * Returns the transliterated string to convert any charset to latin.
    */
    public static String transliterate(String input) {
        Transliterator transliterator = Transliterator.getInstance(TRANSLITERATE_ID + "; " + NORMALIZE_ID);
        String result = transliterator.transliterate(input);
        return result;
    }

Se è necessario convertire " òéisöç- > oeisoc " ;, puoi utilizzare questo come punto di partenza:

public class AsciiUtils {
    private static final String PLAIN_ASCII =
      "AaEeIiOoUu"    // grave
    + "AaEeIiOoUuYy"  // acute
    + "AaEeIiOoUuYy"  // circumflex
    + "AaOoNn"        // tilde
    + "AaEeIiOoUuYy"  // umlaut
    + "Aa"            // ring
    + "Cc"            // cedilla
    + "OoUu"          // double acute
    ;

    private static final String UNICODE =
     "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"             
    + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" 
    + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" 
    + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1"
    + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" 
    + "\u00C5\u00E5"                                                             
    + "\u00C7\u00E7" 
    + "\u0150\u0151\u0170\u0171" 
    ;

    // private constructor, can't be instanciated!
    private AsciiUtils() { }

    // remove accentued from a string and replace with ascii equivalent
    public static String convertNonAscii(String s) {
       if (s == null) return null;
       StringBuilder sb = new StringBuilder();
       int n = s.length();
       for (int i = 0; i < n; i++) {
          char c = s.charAt(i);
          int pos = UNICODE.indexOf(c);
          if (pos > -1){
              sb.append(PLAIN_ASCII.charAt(pos));
          }
          else {
              sb.append(c);
          }
       }
       return sb.toString();
    }

    public static void main(String args[]) {
       String s = 
         "The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
       System.out.println(AsciiUtils.convertNonAscii(s));
       // output : 
       // The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c
    }
}

JDK 1.6 fornisce la classe java.text.Normalizer che può essere utilizzata per questa attività.

Guarda un esempio qui

Stringa testata: ÁÂÃÅÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝß

Testato:

L'ultima scelta è la migliore.

Potresti provare a usare unidecode , che è disponibile come ruby ??gem e come modulo perl su cpan . In sostanza, funziona come un'enorme tabella di ricerca, in cui ogni punto di codice unicode si riferisce a un carattere o una stringa ASCII.

Non esiste un modo semplice o generale per fare ciò che vuoi perché è solo la tua opinione soggettiva che queste lettere sembrano loke le lettere latine in cui vuoi convertire. Sono in realtà lettere separate con i loro nomi e suoni distinti che sembrano apparire superficialmente come una lettera latina.

Se vuoi quella conversione, devi creare la tua tabella di traduzione in base a quali lettere latine pensi che le lettere non latine debbano essere convertite.

(Se vuoi solo rimuovere i segni diacritici, ci sono alcune risposte in questa discussione: Come rimuovo i segni diacritici (accenti) da una stringa in .NET? Comunque descrivi un problema più generale)

Sono in ritardo alla festa, ma dopo aver affrontato questo problema oggi, ho trovato questa risposta molto buona:

String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
    .replaceAll("[^\\p{ASCII}]", "");

Riferimento: https://stackoverflow.com/a/16283863

Il problema con " conversione " Unicode arbitrario in ASCII è che il significato di un personaggio dipende dalla cultura. Ad esempio, "ß" in una persona di lingua tedesca dovrebbe essere convertito in "ss" mentre un madrelingua inglese probabilmente lo convertirà in "B".

Aggiungete a ciò il fatto che Unicode ha più punti di codice per gli stessi glifi.

Il risultato è che l'unico modo per farlo è creare una tabella enorme con ciascun carattere Unicode e il carattere ASCII in cui si desidera convertirlo. Puoi prendere una scorciatoia normalizzando i caratteri con accenti al modulo di normalizzazione KD, ma non tutti i caratteri si normalizzano in ASCII. Inoltre, Unicode non definisce quali parti di un glifo sono "accenti".

Ecco un piccolo estratto di un'app che fa questo:

switch (c)
{
    case 'A':
    case '\u00C0':  //  À LATIN CAPITAL LETTER A WITH GRAVE
    case '\u00C1':  //  Á LATIN CAPITAL LETTER A WITH ACUTE
    case '\u00C2':  //  Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX
    // and so on for about 20 lines...
        return "A";
        break;

    case '\u00C6'://  Æ LATIN CAPITAL LIGATURE AE
        return "AE";
        break;

    // And so on for pages...
}

Seguire la classe fa il trucco:

org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top