2009-11-04 8 views
7

Estoy escribiendo una aplicación Java; pero atascado en este puntoPara dividir solo caracteres chinos en Java

Básicamente tienen una cadena de caracteres chinos con también algunas posibles caracteres latinos o números, digamos que:

查詢促進民間參與公共建設法(210BOT法). 

que quieren dividir los caracteres chinos, excepto el latín o números como "BOT" anterior. Así, al final voy a tener este tipo de lista:

[ 查, 詢, 促, 進, 民, 間, 參, 與, 公, 共, 建, 設, 法, (, 210, BOT, 法, ), ., ]

¿Cómo puedo resolver este problema (para Java)?

Respuesta

10

caracteres chinos se encuentra dentro de ciertos rangos de Unicode:

  • 2F00-2FDF: Kangxi
  • 4E00-9FAF: CJK
  • 3400-4DBF: CJK Extensión

Así que todo lo que básicamente lo que hay que hacer es verificar si el punto de código del personaje se encuentra dentro de los rangos conocidos. Este ejemplo es un buen punto de partida para escribir un analizador stackbased/divisor, sólo es necesario extenderlo a separar los dígitos de las letras latinas, que debe ser lo suficientemente obvia (pista: Character#isDigit()):

Set<UnicodeBlock> chineseUnicodeBlocks = new HashSet<UnicodeBlock>() {{ 
    add(UnicodeBlock.CJK_COMPATIBILITY); 
    add(UnicodeBlock.CJK_COMPATIBILITY_FORMS); 
    add(UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS); 
    add(UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT); 
    add(UnicodeBlock.CJK_RADICALS_SUPPLEMENT); 
    add(UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION); 
    add(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS); 
    add(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A); 
    add(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B); 
    add(UnicodeBlock.KANGXI_RADICALS); 
    add(UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS); 
}}; 

String mixedChinese = "查詢促進民間參與公共建設法(210BOT法)"; 

for (char c : mixedChinese.toCharArray()) { 
    if (chineseUnicodeBlocks.contains(UnicodeBlock.of(c))) { 
     System.out.println(c + " is chinese"); 
    } else { 
     System.out.println(c + " is not chinese"); 
    } 
} 

Buena suerte.

+0

Como una extensión, creo una clase de caracteres en una expresión regular. abarcar los rangos de Unicode anteriores también funcionaría. –

+0

No realmente si también desea interceptar en grupos de dígitos/letras/guiones/lo que sea. Un analizador basado en pila es una mejor herramienta para este tipo de trabajo. – BalusC

+0

¿Esto también funciona para japonés y coreano? –

1

Aquí hay un enfoque que tomaría.

Puede usar Character.codePointAt (char [] charArray, índice int) para devolver el valor Unicode para un carácter en su matriz de caracteres.

También necesitará una asignación de caracteres latinos Unicode.

Si mira en la fuente de Character.UnicodeBlock, el bloque LATIN completo es el intervalo [0x0000, 0x0249]. Entonces, básicamente, comprueba si su punto de código Unicode está en algún lugar dentro de ese intervalo.

Sospecho que hay una manera de simplemente usar un Character.Subset para comprobar si contiene su char, pero no he investigado eso.

1

Diclaimer: Soy un novato completo de Lucene.

Usando la última versión de Lucene (3.6.0 al momento de escribir) me las arreglo para acercarme al resultado que necesita.

Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36, Collections.emptySet()); 

    List<String> words = new ArrayList<String>(); 
    TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(original)); 
    CharTermAttribute termAttribute = tokenStream.addAttribute(CharTermAttribute.class); 

    try { 
    tokenStream.reset(); // Resets this stream to the beginning. (Required) 
    while (tokenStream.incrementToken()) { 
     words.add(termAttribute.toString()); 
    } 
    tokenStream.end(); // Perform end-of-stream operations, e.g. set the final offset. 
    } 
    finally { 
    tokenStream.close(); // Release resources associated with this stream. 
    } 

El resultado que obtengo es:

[查, 詢, 促, 進, 民, 間, 參, 與, 公, 共, 建, 設, 法, 210bot, 法] 
Cuestiones relacionadas