2013-02-21 6 views
5

Я использую Scanner и Delimiter для tokenize моего .txt-файла (это домашнее задание, которое мне нужно сделать). Первая версия файла выглядит следующим образом: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 

И я использовал useDelimiter("[ ]*(,)[ ]*") вторую версию файла выглядит следующим образом:

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 

И я не могу придумать регулярное выражение какой бы помогите мне разделить числа пробелом и словами по запятой. Ежемесячно мне нужен массив с 14 значениями (очень хорошо, если одна переменная)

Обратите внимание, что существует несколько пробелов (это делается для того, чтобы сделать это сложнее для нас).

Так что любая помощь будет оценена по достоинству.

P.S. Мы только разрешено использовать разделителей только (не расщепляется и т.д ..)

+0

Есть 'пространство' (\ с) и ' слова '(\ w) и' digit '(\ d) и' word border '(\ b) для регулярного выражения, которые могут вам помочь. –

+0

Вы хотите запятую между окончательным номером и первым словом? – nattyddubbs

+0

Мне не нужно ничего добавлять к файлу, мне просто нужно извлечь значения и поместить их в многомерный массив, в этом случае это будет int [8] [14], слова будут заменены соответствующими номерами. –

ответ

4

Это должно работать, ключевым является положительным просмотром назад ((<?=)) и чередованием (|):

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

Печать:

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

Отлично, спасибо большое. –

2

Вы можете попробовать это (((?<=[0-9]+)\s*(?=[0-9]+))|(,\s*(?=[a-zA-Z]+))|((?<=[0-9]+)\s*(?=[a-zA-Z]+))), выглядит ужасно, но должен работать

+0

Во-первых, это неправильно. Наверное, вы имеете в виду '(\ s *, \ s *) | (\ s +)'. Но это тоже не работает. Это разделило бы «очень хорошее» на два токена. – Alderath

+0

Номера выглядят нормально, но строки содержат только 1 букву. –

+0

обновленный исходный вариант, это должно достичь цели –

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

Попробуйте это:

+0

Снова очень хорошо делится на отдельные лексемы, где он должен быть одним. –

2

Обратите внимание, что Scanner позволяет вам изменить разделитель в любое время. Если вы можете положиться на свой текст ввода, всегда имея 10 номеров в начале и 4 группы слов в конце, то вы можете просто начать с разделителя, который просто разбивается на пробелы (\s+), и после 10 звонков на nextInt(), переключитесь на разделитель который разбивается на запятую и пробелы (\s*,\s*).

Что-то вроде:

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

Это также можно сделать с одним разделителем регулярное выражение с использованием zero-width lookaround assertions, но это, вероятно, немного продвинулся для простой задачи в выполнении домашних заданий.

+0

Благодарим вас за предложение, почему я об этом не подумал раньше :) У меня проблема, 10-й индекс всегда кажется 0. –

+0

А я думаю, что когда вы переключаете разделитель, 'Scanner' doesn 't потребляйте пространство (ы) между последним числом и первым словом, поэтому он получает что-то вроде «хорошего» для первой фразы слова. Я обновил ответ, чтобы сообщить «Сканеру» пропустить пробелы после изменения разделителя. – matts