2013-02-21 10 views
5

Używam skanera i separatora do tokenizacji mojego pliku .txt (to zadanie domowe, które muszę zrobić). Pierwsza wersja pliku wygląda następująco:Dilimiter Java Dilimiter

5,5,5,6,5,8,9,5,6,8, good, very good, excellent, good 
7,7,8,7,6,7,8,8,9,7,very good, Good, excellent, very good 
8,7,6,7,8,7,5,6,8,7 ,GOOD, VERY GOOD, GOOD, AVERAGE 
9,9,9,8,9,7,9,8,9,9 ,Excellent, very good, very good, excellent 
7,8,8,7,8,7,8,9,6,8 ,very good, good, excellent, excellent 
6,5,6,4,5,6,5,6,6,6 ,good, average, good, good 
7,8,7,7,6,8,7,8,6,6 ,good, very good, good, very good 
5,7,6,7,6,7,6,7,7,7 ,excellent, very good, very good, very good 

I Użyłem useDelimiter("[ ]*(,)[ ]*") sekund wersja pliku wygląda następująco:

5 5 5 6 5 8 9 5 6 8 good, very good, excellent, good 
7 7 8 7 6 7 8 8 9 7 very good, Good, excellent, very good 
8 7 6 7 8 7 5 6 8 7 GOOD, VERY GOOD, GOOD, AVERAGE 
9 9 9 8 9 7 9 8 9 9 Excellent, very good, very good, excellent 
7 8 8 7 8 7 8 9 6 8 very good, good, excellent, excellent 
6 5 6 4 5 6 5 6 6 6 good, average, good, good 
7 8 7 7 6 8 7 8 6 6 good, very good, good, very good 
5 7 6 7 6 7 6 7 7 7 excellent, very good, very good, very good 

I nie mogę wymyślić co regexp pomóż mi oddzielać liczby od spacji i słów przecinkiem. Zasadniczo potrzebuję tablicy z 14 wartościami (bardzo dobra jest pojedyncza zmienna).

Uwaga: istnieje wiele spacji (odbywa się to w celu utrudnienia nam działania).

Więc każda pomoc byłaby doceniona.

P.S. Jesteśmy używać wyłącznie Separatory tylko (nie dzieli etc ..)

+0

Istnieją 'przestrzeń' (\ s) i " słowo "(\ w) i" cyfra "(\ d) i" granica słowa "(\ b) klasy znaków dla wyrażenia regularnego, które mogą ci pomóc. –

+0

Czy chcesz wstawić przecinek między ostatnią liczbą a pierwszym słowem? – nattyddubbs

+0

Nie muszę dodawać niczego do pliku, po prostu muszę wyodrębnić wartości i umieścić je w wielowymiarowej tablicy, w tym przypadku byłoby to int [8] [14], słowa zostaną zastąpione odpowiednimi liczbami. –

Odpowiedz

4

To powinno działać, klucz jest pozytywna-lookbehind ((<?=)) i naprzemiennie (|):

String input = "9 9 9 8 9 7 9 8 9 9 Excellent, very good, very good, excellent"; 
Scanner s = new Scanner(input).useDelimiter("(?<=\\d)[\\s,]+|\\s*,\\s*"); 
while (s.hasNext()) { 
    System.out.println("Token: ." + s.next() + "."); 
} 

Wydruki:

Token: .9. 
Token: .9. 
Token: .9. 
Token: .8. 
Token: .9. 
Token: .7. 
Token: .9. 
Token: .8. 
Token: .9. 
Token: .9. 
Token: .Excellent. 
Token: .very good. 
Token: .very good. 
Token: .excellent. 
+0

Doskonały, wielkie dzięki. –

2

Można próbować ten jeden (((?<=[0-9]+)\s*(?=[0-9]+))|(,\s*(?=[a-zA-Z]+))|((?<=[0-9]+)\s*(?=[a-zA-Z]+))), wygląda okropnie, ale powinien działać

+0

Po pierwsze, to jest złe. Chyba masz na myśli '(\ s *, \ s *) | (\ s +)'. Ale to też nie działa. Oddzieliłoby to słowo "bardzo dobry" na dwa żetony. – Alderath

+0

Numery wydają się być w porządku, ale ciągi zawierają tylko 1 literę. –

+0

zaktualizowany wariant początkowy, to powinno osiągnąć cel –

0
String[] str = expression.split("(,\\s+)|(\\s+)"); 

Spróbuj:

+0

Znów bardzo dobrze dzieli się na osobne żetony, w których ma być jeden. –

2

Należy pamiętać, że Scanner umożliwia zmianę ogranicznika w dowolnym momencie. Jeśli możesz polegać na tekście wejściowym, który zawsze zawiera 10 numerów na początku i 4 grupy słów na końcu, możesz po prostu zacząć od separatora, który dzieli się tylko na spacje (\s+), a po 10 wywołaniach na nextInt(), przełącz na ogranicznik który dzieli się na przecinek i spacje (\s*,\s*).

Coś jak:

String input = "5 5 5 6 5 8 9 5 6 8 good, very good, excellent, good"; 
Scanner scanner = new Scanner(input).useDelimiter("\\s+"); 
int[] results = new int[14]; 
for (int i = 0; i < 10; ++i) { 
    results[i] = scanner.nextInt(); 
} 
scanner.useDelimiter("\\s*,\\s*"); 
scanner.skip("\\s*"); 
for (int i = 10; i < 14; ++i) { 
    String wordPhrase = scanner.next(); 
    int wordValue; 
    if ("average".equalsIgnoreCase(wordPhrase)) 
     wordValue = 1; 
    else if ("good".equalsIgnoreCase(wordPhrase)) 
     wordValue = 2; 
    else if ("very good".equalsIgnoreCase(wordPhrase)) 
     wordValue = 3; 
    else if ("excellent".equalsIgnoreCase(wordPhrase)) 
     wordValue = 4; 
    else 
     wordValue = 0; 
    results[i] = wordValue; 
} 

Jest również możliwe, aby to zrobić za pomocą jednego regex ogranicznika przy użyciu zero-width lookaround assertions, ale jest to prawdopodobnie nieco rozszerzone na proste zadanie domowe.

+0

Dziękuję za sugestię, dlaczego wcześniej o tym nie pomyślałem :) Mam problem, 10. indeks zawsze wydaje się być 0. –

+0

Ah whoops, domyślam się, kiedy przełączasz separator, 'Scanner' doesn Zużywa spację między ostatnią liczbą a pierwszym słowem, więc otrzymuje słowo "dobre" dla pierwszego słowa. Zaktualizowałem odpowiedź, aby powiedzieć "skanerowi", aby przeskakiwał spacje po zmianie ogranicznika. – matts