在字符串的第一个字母前添加点号如何做?

huangapple go评论116阅读模式
英文:

How to add dot before the first letter in a string?

问题

在Java中,您可以使用正则表达式和字符串操作来实现这个任务。下面是一个示例代码:

String s = " GOTO ok1";
// 使用正则表达式查找符合条件的部分
String result = s.replaceAll("(?<=\\s)([A-Za-z])", ".$1");
System.out.println(result);

在Groovy中,您也可以使用正则表达式和闭包来实现这个任务。下面是一个示例代码:

def s = " GOTO ok1"
// 使用正则表达式和闭包来替换字符串
def result = s.replaceAll(/(?<=\s)([A-Za-z])/) { match ->
    ".${match}"
}
println(result)

这两种方法都会将字符串中满足条件的位置添加点号,保留了前导空格。

英文:

Consider this string s = &quot; GOTO ok1&quot;.
How to add a efficient if check whether there exists only a single dot before a letter and after a space.
If dot doesn't exists, I want to add a dot before the first letter.
I want the string to be this s = &quot; .GOTO ok1&quot;. Notice it still holds the leading space.

How to efficiently do this in java(using regex)/ groovy (using closures)?
Does a one or two liner code exists for this ?

答案1

得分: 2

In Java, you can try something like this:

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

It would produce the following outputs:

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

Matcher.replaceFirst replaces the first occurrence of the pattern with the provided replacement. $1 and $2 in the replacement string are references to capture groups within the pattern.

Given the string " ....GOTO ok1":

  • Full pattern match: " ....G"
  • Group 1: " " (leading spaces)
  • Group 2: "G" (the first letter)
  • Thus, " ....G" is replaced with " .G".

In practice, it's better to compile the pattern once and reuse it:

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

}

Performance-wise, regular expressions can be expensive. A more efficient approach would be a simple loop:

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();
}
英文:

In Java you could try something like this:

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

It would produce following outputs:

&quot; GOTO ok1&quot;    -&gt; &quot; .GOTO ok1&quot;,
&quot; .GOTO ok1&quot;   -&gt; &quot; .GOTO ok1&quot;,
&quot;GOTO ok1&quot;     -&gt; &quot;.GOTO ok1&quot;,
&quot;  ..GOTO ok1&quot; -&gt; &quot;  .GOTO ok1&quot;,
&quot;       &quot;      -&gt; &quot;       &quot;

Matcher.replaceFirst replaces first occurrence of the pattern with the provided replacement. $1 and $2 in the replacement string are references to capture-groups within the pattern:

given string &quot; ....GOTO ok1&quot;:

  • full pattern match: &quot; ....G&quot;
  • group 1: &quot; &quot; (leading spaces)
  • group 2: &quot;G&quot; (first letter)
  • thus, &quot; ....G&quot; is replaced with &quot; .G&quot;

In practice you would rather want to compile the pattern once and reuse it:

class RegexTest {

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

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

}

Performance-wise, regular expressions are pretty expensive, the most effective would be a simple loop:

String format(String in) {
    StringBuilder builder = new StringBuilder();
    for(int i=0; i&lt;in.length(); i++) {
        switch (in.charAt(i)) {
            case &#39; &#39;:
                builder.append(&#39; &#39;);
                break;
            case &#39;.&#39;:
                break;
            default:
                builder.append(&quot;.&quot;).append(in.substring(i));
                return builder.toString();
        }
    }
    return builder.toString();
}

答案2

得分: 0

如果您想处理一个大文本以查找这些出现次数,我认为不可能只用2行代码。希望这对您有所帮助或提供了一些想法:

String d = " GOTO ok1";
String b = ".";
StringBuilder builder = new StringBuilder(d);
builder.deleteCharAt(0);
System.out.println(b + builder); // 在您的示例中可以完成任务,但可能不是您要寻找的

String s = " .GOTO ok1";
String count = s.trim();
System.out.println(count); // 这只会去掉空格

int n = 2;
String upToNCharacters = s.substring(0, Math.min(s.length(), n));
int x = upToNCharacters.indexOf('.');
// 在这里,您可以添加一个条件,如果x是0或1,那么"."存在
// 但这不符合您要求的2行代码

System.out.println(x);
英文:

If you are looking to process a large text looking for these occurrences i don't think its possible in 2 lines of code.Hope this helps or gives you some ideas:

    String  d = &quot; GOTO ok1&quot;;
    String  b = &quot; .&quot;;
    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 = &quot; .GOTO ok1&quot;;
    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(&#39;.&#39;);
    // Here you can add IF x is 0 or 1 then &quot;.&quot; exists
    // But it is not 2 lines of code as you requested
    
    System.out.println(x);

huangapple
  • 本文由 发表于 2020年8月7日 17:15:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/63298790.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定