0

What would be a proper way - best practice - to replace a word (character sequence) in a String with another, yet preserve the case of the original? Specifically, if the original is all uppercase, the replacement word should be as well. If the original is all lowercase, the replacement word should be as well. If the original begins with an uppercase character, and the rest is lowercase, the replacement word should be as well.

I presently implement this with three conditional checks, which works fine for my purposes. But it seems to me that there must be a better 'best practice' way, possibly, but not necessarily, with regex. This is meant to be a discussion of possible best or better practice for edification of existing best practice, not a solicitation to solve a trivial coding issue that is already solved and implemented.

A concrete example. In an application that can be run on multiple platforms, all strings containing "click" would be translated to "tap" when run on a mobile device, as would "Click" become "Tap", and "CLICK" become "TAP". In my own case, I do this in a far more general way with a map of words and their replacements, but that is an example of a specific.

drawk
  • 309
  • 4
  • 10
  • 2
    How about the case where the replacement text has a different length from the original text? E.g. replace "abcDe" with "xy". What should be the output? – VHS Mar 11 '17 at 19:19
  • Yeah, in this case, mixed case - except for the first letter) won't be accounted for, for that very reason. So, "abcDe" would become "xy", but "AbcDe" would become "Xy" Edited the original with an example. – drawk Mar 11 '17 at 19:22
  • Welcome to Stack Overflow! We are a question-and-answer site, not a coders-for-hire service. Please narrow your question down to a specific problem that would be on-topic for this site. See: [Why is "Can someone help me?" not an actual question?](http://meta.stackoverflow.com/q/284236) and [How to ask a good question when I'm not sure what I'm looking for?](https://meta.stackoverflow.com/questions/262527/how-to-ask-a-good-question-when-im-not-sure-what-im-looking-for) – Joe C Mar 11 '17 at 19:23
  • Possible duplicate of [java String, replaceall() but keep case in original string](http://stackoverflow.com/questions/33133965/java-string-replaceall-but-keep-case-in-original-string) – Syd Mar 11 '17 at 19:30
  • @Mel, it is not a duplicate, this question is about strings, not regexes. – Grzegorz Górkiewicz Mar 11 '17 at 19:34
  • @Mel - read that first, but it is not at all the same question. In that case, the author was unsure of how to keep the original word via backreferences. – drawk Mar 11 '17 at 19:34
  • @drawk Your question was never unclear. It's just not appropriate for this site. Please read the links that I gave you earlier to understand why this is. – Joe C Mar 11 '17 at 19:37

2 Answers2

1

Given the target substring:

  • Create a StringBuilder.

  • Loop through target and the replacement string in parallel, character by character.

  • In each iteration, examine the case of the target character​.

  • Add to the StringBuilder the corresponding replacement character, changed to that case.

  • Upon exit from the loop, execute a standard replaceAll of target in the original string with the toString of the StringBuilder.

Adjust the above as needed for target and replacement being null, empty, or of different lengths.

Lew Bloch
  • 3,364
  • 1
  • 16
  • 10
1

You can do it the following way (in one line) if using regex is not mandatory:

s1 = s1.replace(s2, s3.chars().mapToObj(i -> Character.isUpperCase(s2.charAt(s3.indexOf((char)i))) ? Character.toString(Character.toUpperCase((char)i)) : Character.toString(Character.toLowerCase((char)i))).collect(Collectors.joining()));

Here s1 is the original string, s2 is the string to be replaced and s3 is the new string to replace s2 keeping the case of s2.

VHS
  • 9,534
  • 3
  • 19
  • 43