I have two Strings and a Json response :
InputString = "ab";
OutputString = "";
Json(example, not real one): Array(From:a,to:bhduh - From:b, to:eiaja).
*Json isn't a real response, it has 2 records for this example .
What i want to do is to replace a with bhduh and b with eiaja, I have a JSON loop which tell me to what i should replace, and i need to do it inside that loop, So here's what i tried :
InputString = InputString.replace(From,To);
Output
eiajahduheiaja
Expected Output
bhduheiaja
This's happening because in the first loop, it's changing a, and in the second loop, there's two b, the b in bhduh and b in the normal String.
The loop times depend on letters count, so sometimes it can be 5 or 6, depending on the server Json response.
What i want is to have the Expected Output, any ideas ?
It is unclear what JSON you have, but I'm guessing your problem is that you are replacing a with bhduh, (which contains a b), then you try to replace b with some other stuff. Obviously that isn't correct.
You need to loop over your initial input, then append your replacements to some other string, not replace upon your input.
For example, using a HashMap
public static void main (String[] args) throws java.lang.Exception
{
String input = "ab";
HashMap<Character, String> replacements = new HashMap<Character, String>() {{
put('a', "bhduh");
put('b', "eiaja");
}};
StringBuilder sb = new StringBuilder();
for (char c : input.toCharArray()) {
String rep = replacements.get(c);
if (rep != null) {
sb.append(rep);
}
}
System.out.println(sb.toString());
}
Example
If you replace all the original a's with some special character like - and all the original b's with another special character like *
you should then be able to replace the special characters with the desired phrase.
Something like:
String str = "ab";
str =str.replace("a", "-");
str =str.replace("b", "*");
str =str.replace("-", "bhduh");
str =str.replace("*","eiaja");
System.out.println(str);
very likely not the best solution but possibly a working one for now.
Related
I am writing a cryptography program that converts the ciphertext to plaintext. By the letter's frequency, I manually crack all the cipher's letters to plaintext, and there is no patterns, so I need to write a loop that contains 26 times, to convert every single letter in the string to another letter.
My first try is using the replace statement in java,
which will be like this
str=str.replaceAll("A","E");
The question is, for instance, I input a string like this abc
and my key will be like this "replace a with c, replace b with p, replace c with q".
The output I want should be cpq, but the output I got is qpq.
Which means I want it be like one time convert.
So I am trying to use the loop, using the if
The way I am doing it is:
for (i=1;i<string.length;i++)
if (char[i]=="a")
char [i] ="b";
The error tells me that I can't convert string to char.
And also, I want to ask if I put the other 25 if statements inside this statement or pararall them?
To answer the second part of your question: I would not add 25 single if statements in your loop but instead use a Map<Character, Character> to store your replacements.
A complete solution could look like this:
public static void main(String[] args) {
Map<Character, Character> replacements = new HashMap<>();
replacements.put('a', 'c');
replacements.put('b', 'p');
replacements.put('c', 'q');
String input = "abcd";
StringBuilder output = new StringBuilder();
for (Character c : input.toCharArray()) {
output.append(replacements.getOrDefault(c, c));
}
System.out.println(output.toString());
}
This will keep characters you don't have a replacement for. Output:
cpqd
You can solve this as :
String str = "abc";
char [] ch = str.toCharArray();
for(int i=0; i<str.length(); i++){
if('a'==str.charAt(i)){
ch[i] = 'c';
}
if('b'==str.charAt(i)){
ch[i] = 'p';
}
if('c'==str.charAt(i)){
ch[i] = 'q';
}
}
System.out.println(String.valueOf(ch));
You can't convert a String to a char. So you need to either use all Strings or all chars. Instead of using the double quotes for String you could use the single quotes for char like this:
char[i]=='b'
and
char[i] = 'b';
Also instead of using a long if/else statement you could either use a switch statement, or even better you could create and use a Map to store the conversions in key/value pairs.
okay.
this is my first post here and I'm kind of new to java
so my question is simple :
is there any instruction in java that remove special characters from a string ?
my string should be only letters
so when the user enters a spacebar or a point or whatever that isn't a letter
it should be removed or ignored
well my idea was about making an array of characters and shift letters to the left each time there is something that isn't a letter
so I wrote this code knowing that x is my string
char h[]=new char [d];
for (int f=0;f<l;f++)
{
h[f]=x.charAt(f);
}
int ii=0;
while (ii<l)
{
if(h[ii]==' '||h[ii]==','||h[ii]=='-'||h[ii]=='\\'||h[ii]=='('||h[ii]==')'||h[ii]=='_'||h[ii]=='\''||h[ii]=='/'||h[ii]==';'||h[ii]=='!'||h[ii]=='*'||h[ii]=='.')
{
for(int m=ii;m<l-1;m++)
{
h[m]=h[m+1];
}
d=d-1;
ii--;
}
ii++;
}
well this works it removes the special char but I can't include all the exceptions in the condition I wonder if there is something easier :)
As others have said Strings in Java are immutable.
One way to catch all characters you do not want is to only allow the ones you want:
final String input = "some string . ";
final StringBuffer sb = new StringBuffer();
final String permittedCharacters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (char c : input.toCharArray()){
if (permittedCharacters.indexOf(c)>=0){
sb.append(c);
}
}
final String endString = sb.toString();
Short answer - No, String is immutable. But you can use StringBuffer instead. This c ass contains deleteCharAt(int) method, that can be useful.
I have a requirement to get the substring of a string based on a condition.
String str = "ABC::abcdefgh||XYZ::xyz";
If input is "ABC", check if it contains in str and if it presents then it should print abcdefgh.
In the same way, if input is "XYZ", then it should print xyz.
How can i achieve this with string manipulation in java?
If I've guessed the format of your String correctly, then you could split it into tokens with something like this:
String[] tokens = str.split("||");
for(String token : tokens)
{
// Cycle through each token.
String key = token.split("::")[0];
String value = token.split("::")[1];
if(key.equals(input))
{
// input being the user's typed in value.
return value;
}
}
But let's have a think for a minute. Why keep this in a String, when a HashMap is a much cleaner solution to your problem? Stick the String into a config file, and on load,
some code can perform a similar task:
Map<String, String> inputMap = new HashMap<String, String>();
String[] tokens = str.split("||");
for(String token : tokens)
{
// Cycle through each token.
String key = token.split("::")[0];
String value = token.split("::")[1];
inputMap.put(key, value);
}
Then when the user types something in, it's as easy as:
return inputMap.get(input);
The idea is that, you should split your string with the delimiters of "::" and "||" , i.e. whichever of them is encountered it will be treated as a delimiter. So, the best way for achieving that is using regular expressions, I think.
String str = "ABC::abcdefgh||XYZ::xyz";
String[] parts = str.split("[::]|[/||]");
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < parts.length - 2; i += 4) {
if (!parts[i].equals("")) {
map.put(parts[i], parts[i + 2]);
}
}
Short and concise, your code is ready. The for loop seems weird, if anyone comes up with a better regex for splitting (to get rid of the empty strings), it will become cleaner. I'm not a regex expert, so any suggestions are welcome.
Use the contains method to see if it has the sub string: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#contains%28java.lang.CharSequence%29
You could do it as follows:
String[] parts = st.split("||");
if (parts[0].startsWith("ABC")) {
String[] values = parts[0].split("::");
System.out.println(values[1]);
} else {
if (parts[1].startsWith("XYZ") {
String[] values = parts[0].split("::");
System.out.println(values[1]);
}
}
The above code will check first if ABC is there. If yes, it will print the result and then stop. If not, it will check the second section of the code to see if it starts with XYZ and then print the result. You can change it to suit your needs.
I have a method that converts all the first letters of the words in a sentence into uppercase.
public static String toTitleCase(String s)
{
String result = "";
String[] words = s.split(" ");
for (int i = 0; i < words.length; i++)
{
result += words[i].replace(words[i].charAt(0)+"", Character.toUpperCase(words[i].charAt(0))+"") + " ";
}
return result;
}
The problem is that the method converts each other letter in a word that is the same letter as the first to uppercase. For example, the string title comes out as TiTle
For the input this is a title this becomes the output This Is A TiTle
I've tried lots of things. A nested loop that checks every letter in each word, and if there is a recurrence, the second is ignored. I used counters, booleans, etc. Nothing works and I keep getting the same result.
What can I do? I only want the first letter in upper case.
Instead of using the replace() method, try replaceFirst().
result += words[i].replaceFirst(words[i].charAt(0)+"", Character.toUpperCase(words[i].charAt(0))+"") + " ";
Will output:
This Is A Title
The problem is that you are using replace method which replaces all occurrences of described character. To solve this problem you can either
use replaceFirst instead
take first letter,
create its uppercase version
concatenate it with rest of string which can be created with a little help of substring method.
since you are using replace(String, String) which uses regex you can add ^ before character you want to replace like replace("^a","A"). ^ means start of input so it will only replace a that is placed after start of input.
I would probably use second approach.
Also currently in each loop your code creates new StringBuilder with data stored in result, append new word to it, and reassigns result of output from toString().
This is infective approach. Instead you should create StringBuilder before loop that will represent your result and append new words created inside loop to it and after loop ends you can get its String version with toString() method.
Doing some Regex-Magic can simplify your task:
public static void main(String[] args) {
final String test = "this is a Test";
final StringBuffer buffer = new StringBuffer(test);
final Pattern patter = Pattern.compile("\\b(\\p{javaLowerCase})");
final Matcher matcher = patter.matcher(buffer);
while (matcher.find()) {
buffer.replace(matcher.start(), matcher.end(), matcher.group().toUpperCase());
}
System.out.println(buffer);
}
The expression \\b(\\p{javaLowerCase}) matches "The beginning of a word followed by a lower-case letter", while matcher.group() is equal to whats inside the () in the part that matches. Example: Applying on "test" matches on "t", so start is 0, end is 1 and group is "t". This can easily run through even a huge amount of text and replace all those letters that need replacement.
In addition: it is always a good idea to use a StringBuffer (or similar) for String manipulation, because each String in Java is unique. That is if you do something like result += stringPart you actually create a new String (equal to result + stringPart) each time this is called. So if you do this with like 10 parts, you will in the end have at least 10 different Strings in memory, while you only need one, which is the final one.
StringBuffer instead uses something like char[] to ensure that if you change only a single character no extra memory needs to be allocated.
Note that a patter only need to be compiled once, so you can keep that as a class variable somewhere.
passing 0 as a limit argument prevents trailing empty strings, but how does one prevent leading empty strings?
for instance
String[] test = "/Test/Stuff".split("/");
results in an array with "", "Test", "Stuff".
Yeah, I know I could roll my own Tokenizer... but the API docs for StringTokenizer say
"StringTokenizer is a legacy class that is retained for compatibility
reasons although its use is discouraged in new code. It is recommended
that anyone seeking this functionality use the split"
Your best bet is probably just to strip out any leading delimiter:
String input = "/Test/Stuff";
String[] test = input.replaceFirst("^/", "").split("/");
You can make it more generic by putting it in a method:
public String[] mySplit(final String input, final String delim)
{
return input.replaceFirst("^" + delim, "").split(delim);
}
String[] test = mySplit("/Test/Stuff", "/");
Apache Commons has a utility method for exactly this: org.apache.commons.lang.StringUtils.split
StringUtils.split()
Actually in our company we now prefer using this method for splitting in all our projects.
I don't think there is a way you could do this with the built-in split method. So you have two options:
1) Make your own split
2) Iterate through the array after calling split and remove empty elements
If you make your own split you can just combine these two options
public List<String> split(String inString)
{
List<String> outList = new ArrayList<>();
String[] test = inString.split("/");
for(String s : test)
{
if(s != null && s.length() > 0)
outList.add(s);
}
return outList;
}
or you could just check for the delimiter being in the first position before you call split and ignore the first character if it does:
String delimiter = "/";
String delimitedString = "/Test/Stuff";
String[] test;
if(delimitedString.startsWith(delimiter)){
//start at the 1st character not the 0th
test = delimitedString.substring(1).split(delimiter);
}
else
test = delimitedString.split(delimiter);
I think you shall have to manually remove the first empty string. A simple way to do that is this -
String string, subString;
int index;
String[] test;
string = "/Test/Stuff";
index = string.indexOf("/");
subString = string.substring(index+1);
test = subString.split("/");
This will exclude the leading empty string.
I think there is no built-in function to remove blank string in Java. You can eliminate blank deleting string but it may lead to error. For safe you can do this by writing small piece of code as follow:
List<String> list = new ArrayList<String>();
for(String str : test)
{
if(str != null && str.length() > 0)
{
list.add(str);
}
}
test = stringList.toArray(new String[list.size()]);
When using JDK8 and streams, just add a skip(1) after the split. Following sniped decodes a (very wired) hex encoded string.
Arrays.asList("\\x42\\x41\\x53\\x45\\x36\\x34".split("\\\\x"))
.stream()
.skip(1) // <- ignore the first empty element
.map(c->""+(char)Integer.parseInt(c, 16))
.collect(Collectors.joining())
You can use StringTokenizer for this purpose...
String test1 = "/Test/Stuff";
StringTokenizer st = new StringTokenizer(test1,"/");
while(st.hasMoreTokens())
System.out.println(st.nextToken());
This is how I've gotten around this problem. I take the string, call .toCharArray() on it to split it into an array of chars, and then loop through that array and add it to my String list (wrapping each char with String.valueOf). I imagine there's some performance tradeoff but it seems like a readable solution. Hope this helps!
char[] stringChars = string.toCharArray();
List<String> stringList = new ArrayList<>();
for (char stringChar : stringChars) {
stringList.add(String.valueOf(stringChar));
}
You can only add statement like if(StringUtils.isEmpty(string)) continue; before print the string. My JDK version 1.8, no Blank will be printed.
5
this
program
gives
me
problems