2013-02-21 7 views
5

Ich benutze Scanner und ein Trennzeichen, um meine .txt-Datei zu tokenisieren (es ist eine Hausaufgabe, die ich machen muss). Erste Version der Datei sieht wie folgt aus:Java Scanner 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 

Und ich habe useDelimiter("[ ]*(,)[ ]*") Sekunden-Version der Datei sieht wie folgt verwendet:

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 

Und ich kann nicht kommen mit einem regexp die würden hilf mir, Zahlen durch Leerzeichen und Wörter durch Komma zu trennen. Im Wesentlichen brauche ich ein Array mit 14 Werten (sehr gut ist eine einzige Variable)

Beachten Sie, dass es mehrere Leerzeichen gibt (dies geschieht absichtlich, um es für uns schwieriger zu machen).

So jede Art von Hilfe würde geschätzt werden.

P.S. Wir sind nur Trennzeichen nur (keine Splits etc ..) zu verwenden, erlaubt

+0

Es gibt 'Raum' (\ s) und ' word '(\ w) und' digit '(\ d) und' word boundary '(\ b) Zeichenklassen für Regex, die Ihnen helfen könnten. –

+0

Möchten Sie ein Komma zwischen der endgültigen Nummer und dem ersten Wort? – nattyddubbs

+0

Ich muss nichts zur Datei hinzufügen, ich muss einfach die Werte extrahieren und in ein multidimensionales Array setzen. In diesem Fall wäre es int [8] [14], die Wörter werden durch entsprechende Zahlen ersetzt. –

Antwort

4

Dies sollte funktionieren, ist der Schlüssel der positiven Lookbehind ((<?=)) und Wechsel (|):

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() + "."); 
} 

Drucke:

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

Perfekt, vielen Dank. –

2

Sie können versuchen diese (((?<=[0-9]+)\s*(?=[0-9]+))|(,\s*(?=[a-zA-Z]+))|((?<=[0-9]+)\s*(?=[a-zA-Z]+))), sieht schrecklich, aber sollten diese

+0

Erstens ist das falsch. Ich denke du meinst '(\ s *, \ s *) | (\ s +)'. Aber das funktioniert auch nicht. Es würde "sehr gut" in zwei Token aufteilen. – Alderath

+0

Zahlen scheinen in Ordnung zu sein, aber die Strings enthalten jeweils nur einen Buchstaben. –

+0

aktualisiert erste Variante, sollte dies das Ziel erreichen –

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

Versuchen arbeiten:

+0

Wieder ist sehr gut in separate Token aufgeteilt, wo es eine einzige sein soll. –

2

Beachten Sie, dass Scanner können Sie das Trennzeichen jederzeit ändern. Wenn Sie sich darauf verlassen können, dass Ihr Eingabetext immer 10 Ziffern am Anfang und 4 Wortgruppen am Ende hat, können Sie einfach mit einem Trennzeichen beginnen, das nur Leerzeichen trennt (\s+) und nach 10 Aufrufen an nextInt() zu einem Trennzeichen wechseln Dies teilt sich auf ein Komma und Leerzeichen (\s*,\s*).

Etwas wie:

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; 
} 

Es ist auch möglich, dies mit einem einzigen Begrenzer Regex zu tun zero-width lookaround assertions verwenden, aber das ist wahrscheinlich ein bisschen für ein einfaches Hausaufgabe Problem fortgeschritten.

+0

Vielen Dank für den Vorschlag, warum habe ich nicht vorher daran gedacht :) Ich habe ein Problem tho, 10. Index scheint immer 0 zu sein. –

+0

Ah whoops, ich denke, wenn Sie das Trennzeichen, die 'Scanner' gehen doesn Die Leerzeichen zwischen der letzten Zahl und dem ersten Wort werden nicht konsumiert, daher wird für die erste Wortphrase etwas wie "gut" angezeigt. Ich habe die Antwort aktualisiert, um dem Scanner zu sagen, dass er Leerzeichen überspringen soll, nachdem er das Trennzeichen geändert hat. – matts