Учитывая ваше описание, я предполагаю, что после NNDDDDD
части, первая A
на самом деле будет N
, а не A
, поскольку в противном случае между участками DDDDD
и AAAA
нет сплошной границы.
Итак, ваша строка на самом деле выглядит как NNDDDDDNAAA
, и вы хотите заменить часть NAAA
пробелами. Учитывая это, регулярное выражение может быть переписано как таковое: (\\D+\\d+)(\\D.+)
Положительный lookbehind в Java требует шаблона фиксированной длины; Вы не можете использовать шаблоны +
или *
. Вместо этого вы можете использовать фигурные скобки и указать максимальную длину. Например, вы можете использовать {1,9}
вместо каждого +
, и он будет соответствовать между 1 и 9 символами: (?<=\\D{1,9}\\d{1,9})(\\D.+)
Единственной проблемой здесь вы соответствием последовательности Naaa в одной игре, так что использование "NNNDDDDNAAA".replaceAll("(?<=\\D{1,9}\\d{1,9})(\\D.+)", " ")
приведет при замене всей последовательности NAAA
на единое пространство, а не на несколько пробелов.
Вы можете взять начальный разделитель совпадения и длину строки и использовать это, чтобы добавить правильное количество пробелов, но я не вижу смысла. Я думаю, вам лучше с вашим оригинальным решением; Его просто и легко следовать.
Если вы ищете небольшую дополнительную скорость, вы можете скомпилировать свой шаблон вне функции и использовать StringBuilder или StringBuffer для создания вашего вывода. Если вы создаете большую строку из всех этих элементов NNDDDDDAAAAA, полностью работайте в StringBuilder, пока не закончите добавление.
class Test {
public static Pattern p = Pattern.compile("(\\D+\\d+)(\\D.+)");
public static StringBuffer replace(String input) {
StringBuffer output = new StringBuffer();
Matcher m = Test.p.matcher(input);
if(m.matches())
output.append(m.group(1)).append(m.group(2).replaceAll("."," "));
return output;
}
public static void main(String[] args) {
String input = args[0];
long startTime;
StringBuffer tests = new StringBuffer();
startTime = System.currentTimeMillis();
for(int i = 0; i < 50; i++)
{
tests.append("Input -> Output: '");
tests.append(input);
tests.append("' -> '");
tests.append(Test.replace(input));
tests.append("'\n");
}
System.out.println(tests.toString());
System.out.println("\n" + (System.currentTimeMillis()-startTime));
}
}
Update: Я написал быстрое итеративное решение, и провел несколько случайных данных через оба. Итеративное решение примерно в 4-5 раз быстрее.
public static StringBuffer replace(String input)
{
StringBuffer output = new StringBuffer();
boolean second = false, third = false;
for(int i = 0; i < input.length(); i++)
{
if(!second && Character.isDigit(input.charAt(i)))
second = true;
if(second && !third && Character.isLetter(input.charAt(i)))
third = true;
if(second && third)
output.append(' ');
else
output.append(input.charAt(i));
}
return output;
}
Как бы вы сказали разницу между «А» и другими? «Всегда ли« А »приходит после« Д »? – BryanH
Как вы определяете разницу между последним «D» и первым «A»? Является ли группа «А» гарантией того, что она не будет символом типа «D»? –
Curtis Tasker правильный, сначала A после NNDDDD всегда N, остальное - это что угодно. – 2009-07-09 14:15:41