2013-05-19 22 views
5

Voglio ottenere il conteggio delle parole da una stringa. E 'così semplice. Il problema è che la stringa può essere in un linguaggio imprevedibile.Ottieni il conteggio delle parole da una stringa in Unicode (in qualsiasi lingua)

Così, ho bisogno di una funzione di firma int getWordCount(String) con la seguente output di esempio -

getWordCount("供应商代发发货") => 7 
getWordCount("This is a sentence") => 4 

Qualsiasi aiuto su come procedere sarebbe apprezzato :)

+0

Nel testo cinese (?) C'è un separatore tra le parole? –

+0

No there's no separator. Ho copiato le stringhe esatte. – jaibatrik

+0

In tal caso, tenterei di trovare la lingua in base alla quale vengono utilizzate le rune Unicode nella stringa.Quindi utilizzare tali informazioni per determinare come deve essere analizzata la stringa. –

risposta

5

Il concetto di "parola" può essere banale o complessa. Ecco Apache Stanbol Toolkit:

Parola Tokenizzazione: Il rilevamento di singole parole è richiesto dal Stanbol Enhancer per elaborare il testo. Sebbene questo sia banale per la maggior parte delle lingue , è un compito piuttosto complesso per alcune lingue orientali, ad es. cinese, giapponese, coreano. Se non diversamente configurato, Stanbol userà gli spazi bianchi per utilizzare tokenize delle parole da .

Quindi, se il concetto di parola è linguistica, piuttosto che sintattico, è necessario utilizzare un NLP toolkit

La mia soluzione preferita Java è Apache's Open NLP

NOTA: Ho usato http://www.mdbg.net/chindict/chindict.php?page=worddict per tokenize tuo esempio . Implica che ci siano 4 parole non sette.Ho tagliato e incollato (piuttosto frammentato):

testo originale semplificato Pinyin dizionario inglese aggiungere una nuova parola al dizionario tradizionale HSK 供应 商 供应 商 gōng shang ying

fornitore

供應 商 代
代 dài

di sostituire/ad agire per conto di terzi/sostituire// (historical)/(geologico) EON epoca generazione/dinastia/età/periodo


发 FA

di inviare/per mostrare (di un sentimento)/per il rilascio/sviluppare/classificatore per arma da fuoco (round)

發 HSK 4

发 fà

capelli/Taiwan pr. [FA3]

髮 发货
发货 FA Huo

di spedizione/per l'invio di merci

發貨

Questi primi tre caratteri vengono visualizzati in modo da formare un unico parola.

+0

Grazie per il vostro aiuto. Penso che il tuo approccio sia molto logico. Cercherò di trovare alcuni toolkit per vedere come posso risolvere questo problema. – jaibatrik

+0

Buono. Potresti voler iniziare con un tagger PartOfSpeech che rileverà nomi, verbi, ecc. E ci sono quasi certamente alcuni servizi online che aiutano a esplorare il tuo problema. E il tuo problema generale è probabilmente più complesso del semplice trovare parole. –

+0

Conoscete un toolkit/servizio facile per questo? Può essere una buona parola tokenizer? – jaibatrik

1

inglese versione

Per la versione inglese che puoi fare con un Regex piuttosto semplice. Forse ho perso alcuni separatori personalizzati ma:

public static int getWordCount(String str) { 
    return str.split("[\\s,;-]+").length; 
} 

spiegazione Regex:

Split se trova alcuna nel gruppo []:

[ 
\\s Any whitespace character or 
, A comma 
; or a semi-colon 
] 
+ Followed by any patterns in the group any number of times 

versione cinese

Per la versione cinese, è necessario identificare ciò che è separato sono Se ottieni il codice char Unicode dei separatori cinesi e li aggiungi alla regex precedente, otterrai i risultati desiderati.

Test

System.out.println(getWordCount("This is a sentence"));// 4 
System.out.println(getWordCount("This is a sentence")); // 4 
System.out.println(getWordCount("This is a  ,,sentence")); // 4 
+0

Grazie per il tuo suggerimento. Lo proverò – jaibatrik

2

Se assumiamo che ogni lingua ha una (o più) separatore di parola, e si può costruire espressione regolare per quelli di separazione, allora il problema può essere risolto in questo modo:

public String separatorForLanguage(char unicodeChar){ 
     // Find out in which language unicodeChar falls 
     return ""; // return regex of separator of that language 
    } 

    public int wordCount(String sentance){ 
     char unicodeChar = sentance.charAt(0); 
     String separator = separatorForLanguage(unicodeChar); 

     int count = sentance.split(separator).length; 
     if (separator.isEmpty()) { 
      count--; 
     } 

     return count; 
    } 
+0

Grazie per la risposta. In realtà, il testo cinese/giapponese non ha un separatore e questo è il problema. – jaibatrik

+0

@jaibatrik: quindi il separatore è una stringa vuota, suppongo. – Mohayemin

+0

Sì, sembra logico. Grazie per lo pseudocodice ben preparato. Apprezzamento e up-voto! – jaibatrik

5

L'API standard fornisce la BreakIterator per questo tipo di analisi dei confini, ma il supporto locale di Oracle Java 7 non interrompe la stringa di esempio.

Quando ho utilizzato il ICU4J v51.1 BreakIterator ha rotto il campione in [供应, 商代, 发, 发, 货].

// import com.ibm.icu.text.BreakIterator; 
String sentence = "\u4f9b\u5e94\u5546\u4ee3\u53d1\u53d1\u8d27"; 
BreakIterator iterator = BreakIterator.getWordInstance(Locale.CHINESE); 
iterator.setText(sentence); 

List<String> words = new ArrayList<>(); 
int start = iterator.first(); 
int end = iterator.next(); 
while (end != BreakIterator.DONE) { 
    words.add(sentence.substring(start, end)); 
    start = end; 
    end = iterator.next(); 
} 
System.out.println(words); 

Nota: Ho usato Google Translate intuire che "供应 商代 发 发货" era cinese. Ovviamente, non parlo la lingua quindi non posso commentare la correttezza dell'output.

+0

Grazie per aver condiviso. Up-votando anche tu! – jaibatrik

2

Ecco frammento in java

public static int getWordCount(String string) 
{ 
    Pattern pattern = Pattern.compile("[\\w']+|[\\u3400-\\u4DB5\\u4E00-\\u9FCC]"); 
    Matcher matcher = pattern.matcher(string); 
    int count = 0; 
    while(matcher.find()) 
     count++; 
    return count;         
} 

Esempio

//count is 5 
int wordCount = getWordCount("this is popcorny's 電腦"); 
Problemi correlati