开发者

replace / prepend set of characters in string

开发者 https://www.devze.com 2023-02-17 03:03 出处:网络
I wanted to replace some set of characters and I used CharMatcher of Guava for this purpose and now I need to enhance a method - along with the replacement now I need to prepe开发者_开发问答nd some of

I wanted to replace some set of characters and I used CharMatcher of Guava for this purpose and now I need to enhance a method - along with the replacement now I need to prepe开发者_开发问答nd some of the characters as well like '%' -> '!%' , I don't know how to do this with Guava so after reading this question ,I used regex for this purpose. and code is something like -

s.replaceAll("['\\\\]", "\\\\$0");

but it's a part of same method and it looks little inconsistent to use CharMather and regex in the same method for string manipulations, so I was just wondering whether I can use CharMatcher for this purpose as well.

I didn't test whether regex approach is faster than CharMatcher or vice versa, but if CharMatcher can handle this then would like to see how also would like to know which approach is more efficient.


Ok, I think I understood what you want to do.

Guava's CharMatcher does not let you refer to the matched character ("backreference") in the replacement CharSequence.

For example, if you want to replace "i" with "!i", and "j" with "!j", you cannot do:

String string = ...;
CharMatcher.anyOf("ij").replaceFrom(string, "!$0");

You must do:

String string = ...;
string = CharMatcher.is('i').replaceFrom(string, "!i");
string = CharMatcher.is('j').replaceFrom(string, "!j");

Which is annoying, since the code is dirtier (more code), and is less performant (the string characters will be iterated over multiple times).

If you find yourself doing this often, I guess you could create an utility method, inspired from CharMatcher.replaceFrom(), that prepends a String when a character is matched by a given CharMatcher:

public static String prepend(CharSequence sequence, CharMatcher charMatcher, CharSequence toPrepend) {
    if (toPrepend.length() == 0) {
        return sequence.toString();
    }

    String string = sequence.toString();
    int pos = charMatcher.indexIn(string);
    if (pos == -1) {
        return string;
    }

    int len = string.length();
    StringBuilder buf = new StringBuilder((len * 3 / 2) + 16);

    int oldpos = 0;
    do {
        buf.append(string, oldpos, pos);
        buf.append(toPrepend);
        buf.append(string.charAt(pos));
        oldpos = pos + 1;
        pos = charMatcher.indexIn(string, oldpos);
    } while (pos != -1);

    buf.append(string, oldpos, len);
    return buf.toString();
}

And use it like this:

MyCharMatchers.prepend(string, CharMatcher.anyOf("aei"), "!");

I don't know about the performance implications. I think the CharMatcher is faster than regular expressions, but you'd have to benchmark it to be sure.


I wouldn't care about using exclusively CharMatcher if I were you. In fact I don't care about using exclusively Guava, but I care about the excellent design Guava tries to enforce.

If guava can't help you here, just use what you can use. It's not because we use Guava that we have no right to look at other components. If regex are what you need and Guava offers no suitable alternative, then you have all reasons in the world to continue using regex.

Obviously, you might want to encapsulate this in specific methods/classes to make it reusable a la guava. All I'd care about is that the code is readable enough as well as efficient.

For instance, don't use String#replaceAll(), but compile a j.u.regex.Pattern and reuse that pattern and use Pattern#matcher() and Matcher#replaceAll(String).

Example:

public class Regexes {
  public static Function<String,String> replaceAll(String pattern,final String replacement) {
    final Pattern p = Pattern.compile(pattern);
    return new Function<String,String>() {
      public String apply(String input) {
        return p.matcher(input).replaceAll(replacement);
      }
    };
  } // end replace(String, String)
} // end class
...

private static final Function<String,String> myTransformer = Regexes.replaceAll("['\\\\]", "\\\\$0");

This is not a Guava solution (even if there is a Function in it), but it's the most Guava-like solution I could come up to and you still clearly indicate it's a regex (where String#replaceAll(String,String) doesn't.


Looks like you can use the replaceFrom method Or is that not what you are really looking for?


So you want to completely replace one character and append some character to another? I would probably do that in two separate steps for clarity. Personally, I'd find it non-obvious what that regex is doing compared to simple replacement with some easy to understand CharMatchers.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号