0

I am trying to eventually replace a sentence with another set of String. But I hit a roadblock while trying to replace a char in a String with another character of another String.

Here's what I have so far.

String letters = "abcdefghijklmnopqrstuvwxyz";
String encode = "kngcadsxbvfhjtiumylzqropwe";
// the sentence that I want to encode
String sentence = "hello, nice to meet you!";

//swapping each char of 'sentence' with the chars in 'encode'
for (int i = 0; i < sentence.length(); i++) {
    int indexForEncode = letters.indexOf(sentence.charAt(i));
    sentence.replace(sentence.charAt(i), encode.charAt(indexForEncode));
}

System.out.println(sentence);

This way of replacing characters doesn't work. Can someone help me?

hendrahjh
  • 3
  • 3

3 Answers3

4

The reason

sentence.replace(sentence.charAt(i), encode.charAt(indexForEncode));

doesn't work is that Strings are immutable (i.e., they never change). So, sentence.replace(...) doesn't actually change sentence; rather, it returns a new String. You would need to write sentence = sentence.replace(...) to capture that result back in sentence.

OK, Strings 101: class dismissed (;->).

Now with all that said, you really don't want want to keep reassigning your partially encoded sentence back to itself, because you will, almost certainly, find yourself re-encoding characters of sentence that you already encoded. Best to leave sentence in its original form while building up the encoded string one character at a time like this:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < sentence.length(); i++){
    int indexForEncode = letters.indexOf(sentence.charAt(i));
    sb.append(indexForEncode != -1
            ? encode.charAt(indexForEncode)
            : sentence.charAt(i)
    );
}
sentence = sb.toString();
Kevin Anderson
  • 4,568
  • 3
  • 13
  • 21
  • Hi, thank you so much! This worked for me. I wish I could upvote. However, is there an article for me to read on if the chars in 'sentence' aren't alphabets? This gives me an error if I have non alphabet characters. – hendrahjh Mar 18 '21 at 01:54
  • I've updated the code to address that; maybe you're still looking at the old version. You might want to check the [Javadoc for the `indexOf` method](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#indexOf-int-): to see the logic behind my fix. – Kevin Anderson Mar 18 '21 at 02:00
0

I would use a character array as follows. Make the changes to a character array and then use String.valueOf to get the new version of the string.

String letters = "abcdefghijklmnopqrstuvwxyz";
String encode =  "kngcadsxbvfhjtiumylzqropwe";
// the sentence that I want to encode
String sentence = "hello, nice to meet you!";

char[] chars = sentence.toCharArray();
for (int i = 0; i < chars.length; i++){
    int indexForEncode = letters.indexOf(sentence.charAt(i));
    // if index is < 0, use original character, otherwise, encode.
    chars[i] = indexForEncode < 0 ? chars[i] : encode.charAt(indexForEncode);
}
System.out.println(String.valueOf(chars));

Prints

xahhi, tbga zi jaaz wiq!
WJS
  • 36,363
  • 4
  • 24
  • 39
0

You can use codePoints method to iterate over the characters of this string and replace them with characters from another string, if any.

Try it online!

public static void main(String[] args) {
    String letters = "abcdefghijklmnopqrstuvwxyz";
    String encode = "kngcadsxbvfhjtiumylzqropwe";

    String sentence = "hello, nice to meet you!";
    String encoded = replaceCharacters(sentence, letters, encode);
    String decoded = replaceCharacters(encoded, encode, letters);

    System.out.println(encoded); // xahhi, tbga zi jaaz wiq!
    System.out.println(decoded); // hello, nice to meet you!
}
public static String replaceCharacters(String text, String from, String to) {
    // wrong cipher, return unencrypted string
    if (from.length() != to.length()) return text;
    // IntStream over the codepoints of this text string
    return text.codePoints()
            // Stream<Character>
            .mapToObj(ch -> (char) ch)
            // encrypt characters
            .map(ch -> {
                // index of this character
                int i = from.indexOf(ch);
                // if not present, then leave it as it is,
                // otherwise replace this character
                return i < 0 ? ch : to.charAt(i);
            }) // Stream<String>
            .map(String::valueOf)
            // concatenate into a single string
            .collect(Collectors.joining());
}

See also: Implementation of the Caesar cipher