ollie
ollie

Reputation: 255

String manipulation of function names

For this Kata, i am given random function names in the PEP8 format and i am to convert them to camelCase.

(input)get_speed == (output)getSpeed .... (input)set_distance == (output)setDistance

I have a understanding on one way of doing this written in pseudo-code:

loop through the word,
    if the letter is an underscore
        then delete the underscore
        then get the next letter and change to a uppercase
    endIf
endLoop
return the resultant word

But im unsure the best way of doing this, would it be more efficient to create a char array and loop through the element and then when it comes to finding an underscore delete that element and get the next index and change to uppercase.

Or would it be better to use recursion:

function camelCase takes a string
    if the length of the string is 0,
        then return the string
    endIf
    if the character is a underscore
        then change to nothing,
        then find next character and change to uppercase
        return the string taking away the character
    endIf
    finally return the function taking the first character away

Any thoughts please, looking for a good efficient way of handing this problem. Thanks :)

Upvotes: 0

Views: 402

Answers (3)

Adnan Isajbegovic
Adnan Isajbegovic

Reputation: 2307

I would go with this:

divide given String by underscore to array
from second word until end take first letter and convert it to uppercase
join to one word

This will work in O(n) (go through all names 3 time). For first case, use this function:

str.split("_");

for uppercase use this:

String newName = substring(0, 1).toUpperCase() +  stre.substring(1);

But make sure you check size of the string first...

Edited - added implementation

It would look like this:

public String camelCase(String str) {
        if (str == null ||str.trim().length() == 0) return str;
        String[] split = str.split("_");
        String newStr = split[0];
        for (int i = 1; i < split.length; i++) {
            newStr += split[i].substring(0, 1).toUpperCase() +  split[i].substring(1);
        }
        return newStr;
    }

for inputs:

"test"
"test_me"
"test_me_twice"

it returns:

"test"
"testMe"
"testMeTwice"

Upvotes: 1

Assaf
Assaf

Reputation: 1370

It would be simpler to iterate over the string instead of recursing.

String pep8 = "do_it_again";
StringBuilder camelCase = new StringBuilder();

for(int i = 0, l = pep8.length(); i < l; ++i) {
    if(pep8.charAt(i) == '_' && (i + 1) < l) {
        camelCase.append(Character.toUpperCase(pep8.charAt(++i)));
    } else {
        camelCase.append(pep8.charAt(i));
    }
}

System.out.println(camelCase.toString()); // prints doItAgain

Upvotes: 1

Gerald M&#252;cke
Gerald M&#252;cke

Reputation: 11132

The question you pose is whether to use an iterative or a recursive approach. For this case I'd go for the recursive approach because it's straightforward, easy to understand doesn't require much resources (only one array, no new stackframe etc), though that doesn't really matter for this example.

Recursion is good for divide-and-conquer problems, but I don't see that fitting the case well, although it's possible.

An iterative implementation of the algorithm you described could look like the following:

StringBuilder buf = new StringBuilder(input);
for(int i = 0; i < buf.length(); i++){
    if(buf.charAt(i) == '_'){
        buf.deleteCharAt(i);
        if(i != buf.length()){ //check fo EOL
            buf.setCharAt(i, Character.toUpperCase(buf.charAt(i)));
        }
    }
}
return buf.toString();

The check for the EOL is not part of the given algorithm and could be ommitted, if the input string never ends with '_'

Upvotes: 0

Related Questions