2013-05-19 25 views
5

Chcę uzyskać liczbę słów z ciągu. To takie proste. Połów jest taki, że ciąg może być w nieprzewidywalnym języku.Uzyskaj liczbę słów z ciągu znaków w Unicode (w dowolnym języku)

Więc muszę funkcję podpisu int getWordCount(String) z poniższej wyjściu próbki -

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

Każda pomoc jak postępować będą mile widziane :)

+0

w chińskich (?) Tekstu ma separator pomiędzy słowami? –

+0

Nie, nie ma separatora. Skopiowałem dokładne ciągi. – jaibatrik

+0

W tym przypadku chciałbym znaleźć język oparty na tym, które runy unicode są używane w łańcuchu.Następnie użyj tych informacji, aby określić sposób analizowania ciągu znaków. –

Odpowiedz

5

pojęcia "słowo" może być trywialne lub złożone. Oto Apache Stanbol Toolkit:

Słowo tokenizacja: Wykrywanie pojedynczych słów jest wymagane przez Stanbol Enhancer do przetwarzania tekstu. Chociaż jest to banalne dla większości języków , jest to dość skomplikowane zadanie dla niektórych języków wschodnich, np. Chiński, japoński, koreański. Jeśli nie skonfigurowano inaczej, Stanbol użyje białych znaków do tokenizacji słów.

Więc jeśli pojęcie słowa jest językowym, raczej niż składniowym, należy użyć NLP toolkit

Moje preferowane rozwiązanie Java jest Apache's Open NLP

UWAGA: Użyłem http://www.mdbg.net/chindict/chindict.php?page=worddict do tokenize swój przykład . Oznacza to, że istnieją 4 słowa, a nie siedem.Mam wycinane i wklejane (raczej fragmentaryczne):

oryginalny Tekst uproszczony Pinyin English definicja Dodaj nowe słowo do słownika Tradycyjne HSK 供应 商 供应 商 Gong Ying Shang

dostawca

供應 商 代
代 Dai

zastąpił/do działania w imieniu innych/wymienić/generacja/Dynastia/wiek/czas/(historical) era/(geologiczne) eon


发 FA

wysłać/aby pokazać (jeden za uczucie)/wydać/rozwinąć/klasyfikatora dla strzały (rund)

發 HSK 4

发 FA

włosy/Tajwan pr. [FA3]

髮 发货
发货 FA Huo

wysyłką/wysłać towary

發貨

Te pierwsze trzy znaki wydają się tworzyć jedno słowo.

+0

Dzięki za pomoc. Myślę, że twoje podejście jest bardzo logiczne. Spróbuję znaleźć teraz kilka zestawów narzędzi, aby zobaczyć, jak mogę to rozwiązać. – jaibatrik

+0

Dobrze. Możesz zacząć od Tagger PartOfSpeech, który wykrywa rzeczowniki, czasowniki itp. A prawie na pewno niektóre usługi online pomagają odkryć twój problem. Twój ogólny problem jest prawdopodobnie bardziej skomplikowany niż po prostu znalezienie słów. –

+0

Czy znasz łatwy zestaw narzędzi/usługę do tego? Może być dobrym tokenizerem słów? – jaibatrik

1

angielską wersję

Dla wersja angielska można zrobić z dość prostym Regex. I może zostały pominięte niektóre niestandardowe separatory ale:

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

Regex wyjaśnienie:

Podział jeśli znaleźć żadnego w grupie []:

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

chińska wersja

Dla chińska wersja, musisz określić, co separato rs są. Jeśli otrzymasz kod znaku Unicode chińskich separatorów i dodasz je do powyższego wyrażenia regularnego, uzyskasz pożądane wyniki.

Testy

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

Dzięki za twoją sugestię. Spróbuję tego. – jaibatrik

2

Jeśli założymy, że każdy język ma jeden (lub więcej) separator słowo i można zbudować regex dla tych separatora, to problem może być rozwiązany w ten sposób:

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

Dzięki za odpowiedź. W rzeczywistości tekst chiński/japoński nie ma separatora i na tym polega problem. – jaibatrik

+0

@jaibatrik: wtedy separator jest pustym ciągiem, tak przypuszczam. – Mohayemin

+0

Tak, wydaje się to logiczne. Dzięki za dobrze przygotowany pseudokod. Uznanie i up-vote! – jaibatrik

5

Norma API zapewnia BreakIterator dla tego rodzaju analizy granic, ale obsługa locale Oracle 7 locale nie przerywa próbnego łańcucha.

Kiedy użyłem ICU4J v51.1 BreakIterator, zepsułem próbkę do [供应, 商代, 发, 发, 货].

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

Uwaga: użyłem Google Translate się domyślić, że "供应 商代 发 发货" był chiński. Oczywiście nie mówię w tym języku, więc nie mogę wypowiedzieć się na temat poprawności wyników.

+0

Dzięki za udostępnienie. Uprościę również ciebie! – jaibatrik

2

Oto fragment w 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;         
} 

przykładu

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