4

I have a string that looks like this:

CALDARI_STARSHIP_ENGINEERING

and I need to edit it to look like

Caldari Starship Engineering

Unfortunately it's three in the morning and I cannot for the life of me figure this out. I've always had trouble with replacing stuff in strings so any help would be awesome and would help me understand how to do this in the future.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
Travis
  • 47
  • 4
  • 2
    in a few minutes polygenelubricants will come along and write some wicked cleaver regexp that I don't understand... – aioobe May 16 '10 at 07:58
  • 1
    @aioobe: I'm always more than happy to explain regex whenever my answer is unclear, although of course it helps if people also know the basics. – polygenelubricants May 17 '10 at 06:33
  • Sure. You always provide sufficient links etc for me to understand. What I meant was more like, "soon polygenelubricants will surprise me again with what regexps are capable of" :-) I just wrote a reg-exp variant of your solution for fun. I believe it's robust against the `isEmpty` check that you have (but it's probably not as efficient as your solution). – aioobe May 17 '10 at 07:48

5 Answers5

9

Something like this is simple enough:

    String text = "CALDARI_STARSHIP_ENGINEERING";
    text = text.replace("_", " ");
    StringBuilder out = new StringBuilder();
    for (String s : text.split("\\b")) {
        if (!s.isEmpty()) {
            out.append(s.substring(0, 1) + s.substring(1).toLowerCase());
        }
    }
    System.out.println("[" + out.toString() + "]");
    // prints "[Caldari Starship Engineering]"

This split on the word boundary anchor.

See also


Matcher loop solution

If you don't mind using StringBuffer, you can also use Matcher.appendReplacement/Tail loop like this:

    String text = "CALDARI_STARSHIP_ENGINEERING";
    text = text.replace("_", " ");

    Matcher m = Pattern.compile("(?<=\\b\\w)\\w+").matcher(text);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        m.appendReplacement(sb, m.group().toLowerCase());
    }
    m.appendTail(sb);
    System.out.println("[" + sb.toString() + "]");
    // prints "[Caldari Starship Engineering]"

The regex uses assertion to match the "tail" part of a word, the portion that needs to be lowercased. It looks behind (?<=...) to see that there's a word boundary \b followed by a word character \w. Any remaining \w+ would then need to be matched so it can be lowercased.

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • +1 Easy, understandable solution without using 3rd party stuff. – helpermethod May 16 '10 at 08:49
  • I suggest using `StringBuilder` because it is faster. The StringBuffer should replace StringBuilder only when you suppose concurrency issues in a multi-threaded application. – Leni Kirilov May 16 '10 at 12:11
  • @Leni: unfortunately `Matcher.appendReplacement/Tail` only accepts `StringBuffer`. If you want to use `StringBuilder`, then you can't use those methods. – polygenelubricants May 16 '10 at 14:10
4

You can try this:

String originalString = "CALDARI_STARSHIP_ENGINEERING";
String newString =
    WordUtils.capitalize(originalString.replace('_', ' ').toLowerCase());

WordUtils are part of the Commons Lang libraries (http://commons.apache.org/lang/)

In silico
  • 51,091
  • 10
  • 150
  • 143
1

Using reg-exps:

String s = "CALDARI_STARSHIP_ENGINEERING";
StringBuilder camel = new StringBuilder();
Matcher m = Pattern.compile("([^_])([^_]*)").matcher(s);
while (m.find())
    camel.append(m.group(1)).append(m.group(2).toLowerCase());
aioobe
  • 413,195
  • 112
  • 811
  • 826
0

Untested, but thats how I implemented the same some time ago:

s = "CALDARI_STARSHIP_ENGINEERING";
StringBuilder b = new StringBuilder();
boolean upper = true;
for(char c : s.toCharArray()) {
    if( upper ) {
        b.append(c);
        upper = false;
    } else if( c = '_' ) {
        b.append(" ");
        upper = true;
    } else {
        b.append(Character.toLowerCase(c));
    }
}
s = b.toString();

Please note that the EVE license agreements might forbit writing external tools that help you in your careers. And it might be the trigger for you to learn Python, because most of EVE is written in Python :).

Daniel
  • 27,718
  • 20
  • 89
  • 133
  • Yep - if you change else if( c = '_' ) this is fine – Robben_Ford_Fan_boy May 16 '10 at 08:12
  • Daniel, there's EveMon, gtkEveMon, EFT, and the fact that CCP provides both a database dump and an API for this. – Travis May 16 '10 at 17:40
  • Oh. I assume you can't play Eve anymore without your own Trade monitoring system, Guild tracking system and the like? :) – Daniel May 17 '10 at 05:14
  • Nah, there's ISK to be made. Just nice to be able to instantly check what can make the highest profits... and a neat programming project to boot! – Travis May 18 '10 at 23:10
0

Quick and dirty way:

Lower case all

   line.toLowerCase();

Split into words:

   String[] words = line.split("_");

Then loop through words capitalising first letter:

  words[i].substring(0, 1).toUpperCase() 
Robben_Ford_Fan_boy
  • 8,494
  • 11
  • 64
  • 85