15

I am reading in a string

Is Mississippi a State where there are many systems.

I would like to replace the 1st "s" or "S" in each word with "t" or "T" (i.e keeping the same case)...so that the output is:

It Mitsissippi a Ttate where there are many tystems.

I have tried

s= s.replaceFirst("(?i)S", "t"); [which of course didn't work]

and have experimented trying to split the string using a string [] .split(Pattern.quote("\\s")) then trying to figure out how to replaceFirst() each element of the array and then return the values back to a string [but couldn't figure out the right way of doing it].

I thought \\G might help to restart at the next word but have gotten no where. Any help using these 3 methods is appreciated.

4
  • 1
    Why do you replace 'Is' to 'It' if you only need to replace the 1st 's' or 'S' in each work ? Can you correct the layout and give one or more clear example ? Commented Mar 31, 2016 at 4:42
  • 1
    Got it the first occurence of each 's' or 'S' Commented Mar 31, 2016 at 4:44
  • @Hedgebox I hope you have got your answer. But have provided a different approach to solve your problem. See my answer. Commented Mar 31, 2016 at 5:36
  • 2
    One liner in JavaScript: .replace(/(\S*?)([sS])(\S*)/g, (_, $1, $2, $3) => $1 + ($2 == 's' ? 't' : 'T') + $3) Commented Mar 31, 2016 at 11:00

7 Answers 7

10

One option would be to split the string into words, and then use String.replaceFirst() on each word to replace the first occurrence of s with t (or any other letter you want):

Update:

I refactored my solution to find the first occurrence of any s (upper or lower case), and to apply the appropriate conversion on it.

String input = "Is Mississippi a State where there are many systems.";
String[] parts = input.split(" ");
StringBuilder sb = new StringBuilder("");

for (int i=0; i < parts.length; ++i) {
    if (i > 0) {
        sb.append(" ");
    }
    int index = parts[i].toLowerCase().indexOf('s');
    if (index >= 0 && parts[i].charAt(index) == 's') {
        sb.append(parts[i].replaceFirst("s", "t"));
    }
    else {
        sb.append(parts[i].replaceFirst("S", "T"));
    }
}

System.out.println(sb.toString());

Output:

It Mitsissippi a Ttate where there are many tystems.
Sign up to request clarification or add additional context in comments.

8 Comments

@im-biegeleisen your solution is perfect with some adjustments. Check my post
This gets the wrong result for a word like "Systems" with a capital "S" and lower case "s" (at least as I understood the question).
Systems -> Tyttems ... what is the problem?
@Tim Biegeleisen : msandiford seems to be correct... I just tried it...I would want "Systems" to become "Tystems"... only the 1st occurance of either "S" or "s" to "T" or "t"
@BDCoder Sorry, I had a couple of typos in there. I have fixed them and I verified that the actual output matches what is expected.
|
4

Approach-1: Without using replace and split method for better performance.

String str = "Is Mississippi a State where there are many systems.";
System.out.println(str);

char[] cArray = str.toCharArray();
boolean isFirstS = true;
for (int i = 0; i < cArray.length; i++) {
    if ((cArray[i] == 's' || cArray[i] == 'S') && isFirstS) {
        cArray[i] = (cArray[i] == 's' ? 't' : 'T');
        isFirstS = false;
    } else if (Character.isWhitespace(cArray[i])) {
        isFirstS = true;
    }
}
str = new String(cArray);

System.out.println(str);

EDIT: Approach2: As you need to use replaceFirst method and you dont want to use StringBuilder here is an option for you:

String input = "Is Mississippi a State where there are many Systems.";
String[] parts = input.split(" ");
String output = "";

 for (int i = 0; i < parts.length; ++i) {
     int smallSIndx = parts[i].indexOf("s");
     int capSIndx = parts[i].indexOf("S");

     if (smallSIndx != -1 && (capSIndx == -1 || smallSIndx < capSIndx))
         output += parts[i].replaceFirst("s", "t") + " ";
     else
         output += parts[i].replaceFirst("S", "T") + " ";
 }

System.out.println(output); //It Mitsissippi a Ttate where there are many Tystems. 

Note: I prefer approach 1 because it has no overhead for the method replaceFisrt and split , String append or concat

8 Comments

@cricket_007 edited by going to different approach :)
ASCII shifting... It'll work, but it is very specific to this one problem
@cricket_007 yes.... but I hope this will provide a faster solution than other answer.
@mmuzahid: tks for your solution but I am trying to get a better understanding of the uses of replaceFirst...without the use of StringBuilder at this point.
@Hedgebox , Plz see EDIT part , May be it serve your purpose using replaceFirst
|
3

Use below amendment to Tim Biegeleisen's answer (before editing his post)

String input = "Is Mississippi a State where there are many systems.";
String[] parts = input.split(" ");
StringBuilder sb = new StringBuilder("");

for (String part : parts) {
    sb.append(part.replaceFirst("s", "t").replaceFirst("S", "T"));
    sb.append(" ");
}

System.out.println(sb.toString());

Edit - You can use concat()

String input = "Is Mississippi a State where there are many systems.";
String[] parts = input.split(" ");

String output = "";

for (String part : parts) {
    output = output.concat(part.replaceFirst("s", "t").replaceFirst("S", "T") + " ");
}

    System.out.println(output);

Update

    String input = "Is Mississippi a State where there are many Systems.";
    String[] parts = input.split(" ");
    //StringBuilder sb = new StringBuilder("");

    String output = "";

    for (String part : parts) {
        output = output.concat(part.replaceFirst("s", "t") + " ");
    }

    String[] parts2 = output.split(" ");

    output = "";

    for (String part : parts2) {
        output = output.concat(part.replaceFirst("S", "T") + " ");
    }
    System.out.println(output);

8 Comments

I do want to use String methods...is there a way to do it without using StringBuilder?
@Hedgebox FYI StringBuilder provides better performance than +
@Thush-Fdo: msandiford in his comment below...seems to be correct... I just tried it...I would want "Systems" to become "Tystems"... only the 1st occurance of either "S" or "s" to "T" or "t". When I changes "systems" to "Systems" the code produced "Tyttems" not "Tystems".
@Hedgebox : Another solution to come up with this by using two loops as I've update my answer. But this cost your performance. Feel free to use any of the suggestions.
@Thush-Fdo dont take it other-wise, too many EDIT in your answer confused some people to understand.
|
2

I've created a method that -

  • is general purpose,
  • doesn't use replace or split, and
  • only uses one loop.

The following is my code snippet:

public static String replaceFirstOccurance(String sentence, char toChange, char changeWith) {
    StringBuilder temp = new StringBuilder();

    boolean changed = false;
    for (int i = 0; i < sentence.length(); i++) {
        if (!changed) {
            if (sentence.charAt(i) == toChange) {
                temp.append(changeWith);
                changed = true;
            } else if (sentence.charAt(i) == Character.toUpperCase(toChange)) {
                temp.append(Character.toUpperCase(changeWith));
                changed = true;
            } else {
                temp.append(sentence.charAt(i));
            }
        } else {
            if (sentence.charAt(i) == ' ') {
                changed = false;
            }
            temp.append(sentence.charAt(i));
        }
    }

    return temp.toString();
}

Comments

1

My method would be less dependent on those string methods you've mentioned.

String phrase;
String [] parts = phrase.split(" ");

for (int i = 0; i < parts.length; i++ ) {
    for (int j = 0; j < parts[i].length(); j++) {
        if (parts[i].charAt(j) == 's') {
            parts[i] = "t" + parts[i].substring(1);
            break;
        } else if (parts[i].charAt(0) == 'S') {
            parts[i] = "T" + parts[i].substring(1);
            break;
        }
    }
}

String modifiedPhrase = "";

for (int i = 0; i < parts.length; i++ ) {
    modifiedPhrase += parts[i] + " ";
}

Comments

1

There is also a nice, compact, stream-based solution for that:

String result = Stream.of(s.split(" "))
    .map(t -> t.replaceFirst("s", "t"))
    .map(t -> t.replaceFirst("S", "T"))
    .collect(Collectors.joining(" "));

Comments

0
String ss = "Is Mississippi a State where there are many systems.";

String out = "";//replaced string
for (String s : ss.split(" ")) {
    int index = s.toUpperCase().indexOf('S');
    out += (s.replaceFirst("[s,S]", index!= -1 && s.charAt(index) == 'S' 
               ? "T" : "t")) + " ";
}

System.out.println(out);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.