Как добавить точку перед первой буквой в строке? - PullRequest
0 голосов
/ 07 августа 2020

Рассмотрим эту строку s = " GOTO ok1". Как добавить эффективную if проверку, существует ли только одна точка перед буквой и после пробела. Если точки не существует, я хочу добавить точку перед первой буквой. Я хочу, чтобы строка была такой s = " .GOTO ok1". Обратите внимание, что он по-прежнему занимает ведущее пространство.

Как эффективно сделать это в java (с использованием регулярного выражения) / groovy (с использованием замыканий)? Существует ли для этого одно- или двухстрочный код?

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

В Java вы можете попробовать что-то вроде этого:

Pattern.compile("^(\\s*)(?:\\.)*(\\w)").matcher(input).replaceFirst("$1.$2");

Это даст следующие результаты:

" GOTO ok1"    -> " .GOTO ok1",
" .GOTO ok1"   -> " .GOTO ok1",
"GOTO ok1"     -> ".GOTO ok1",
"  ..GOTO ok1" -> "  .GOTO ok1",
"       "      -> "       "

Matcher.replaceFirst заменяет первое вхождение выкройки с предоставленной заменой. $1 и $2 в строке замены - это ссылки на группы захвата в шаблоне:

заданная строка " ....GOTO ok1":

  • полное совпадение с шаблоном: " ....G"
  • группа 1: " " (ведущие пробелы)
  • группа 2: "G" (первая буква)
  • таким образом, " ....G" заменяется на " .G"

На практике вы бы предпочли скомпилировать шаблон один раз и использовать его повторно:

class RegexTest {

    private final static Pattern PATTERN = Pattern.compile("^(\\s*)(?:\\.)*(\\w)");

    @Test
    void test() {
        var examples = Map.of(
            " GOTO ok1",  " .GOTO ok1",
            " .GOTO ok1", " .GOTO ok1",
            "GOTO ok1", ".GOTO ok1",
            "      ..GOTO ok1", "      .GOTO ok1",
            "       ", "       "
        );
        examples.forEach((input, expected) -> {
            assertEquals(expected, PATTERN.matcher(input).replaceFirst("$1.$2"));
        });
    }

}

С точки зрения производительности регулярные выражения довольно дороги, наиболее эффективным было бы простое l oop:

String format(String in) {
    StringBuilder builder = new StringBuilder();
    for(int i=0; i<in.length(); i++) {
        switch (in.charAt(i)) {
            case ' ':
                builder.append(' ');
                break;
            case '.':
                break;
            default:
                builder.append(".").append(in.substring(i));
                return builder.toString();
        }
    }
    return builder.toString();
}
0 голосов
/ 07 августа 2020

Если вы хотите обработать большой текст в поисках этих вхождений, я не думаю, что это возможно в двух строках кода. Надеюсь, это поможет или даст вам некоторые идеи:

    String  d = " GOTO ok1";
    String  b = " .";
    StringBuilder builder = new StringBuilder(d); 
    builder.deleteCharAt(0);
    System.out.println(b+builder); // Does the job in your example but prob not what you are looking for
    
    String s = " .GOTO ok1";
    String count = s.trim();
    System.out.println(count); // This will only get rid of spaces
    
    int n = 2;
    String upToNCharacters = s.substring(0, Math.min(s.length(), n));
    int x = upToNCharacters.indexOf('.');
    // Here you can add IF x is 0 or 1 then "." exists
    // But it is not 2 lines of code as you requested
    
    System.out.println(x);
...