Replacing an unknown pattern size with a character - java

Is there a way to replace a specific repetitive character using regular expressions?
Example:
str = "Anne has nnnn things"
The solution would be:
"Ane has n things"
If a string has two or more instances of one character next to each other, the regular expression should replace them all with just one.

It is possible:
inputString.replaceAll("(.)\\1+", "$1")
Match one character, capture it, repeat it once or more, replace with only the capture.
However this may not be the faster solution. Such a thing is also doable with a simple loop:
public String removeRepetitions(final String input)
{
if (input.isEmpty())
return input;
final int len = input.length();
final StringBuilder sb = new StringBuilder(length);
char current = input.charAt(0);
char c;
sb.append(current);
for (int i = 1; i < len; i++) {
c = input.charAt(i);
if (c != current) {
sb.append(c);
current = c;
}
}
return sb.toString();
}

This should match n that repeats 2 or more times:
/n{2,}/

Related

How can i replace a char in a String using chars from another string (Caesar Cypher)(JAVA)

I'm doing a caesar-cypher. Trying to replace all characters from a string to a certain character from the shifted alphabet.
Here is my code so far
public static String caesarify(String str, int key){
String alphabetNormal = shiftAlphabet(0);
String alphabetShifted = shiftAlphabet(key);
for (int i =0; i < str.length();i++){
for (int c =0; c < alphabetNormal.length(); c++) {
if (str.charAt(i) == alphabetNormal.charAt(c)) {
char replacement = alphabetShifted.charAt(c);
str.replace(str.charAt(i), replacement);
}
}
}
return str;
}
public static String shiftAlphabet(int shift) {
int start =0;
if (shift < 0) {
start = (int) 'Z' + shift + 1;
} else {
start = 'A' + shift;
}
String result = "";
char currChar = (char) start;
for(; currChar <= 'Z'; ++currChar) {
result = result + currChar;
}
if(result.length() < 26) {
for(currChar = 'A'; result.length() < 26; ++currChar) {
result = result + currChar;
}
}
return result;
}
I don't know why the string for example "ILIKEDONUTS" doesn't change to "JMJLFEPOVUT" when it's caesarified.
Don't use replace(), or any replace method, to replace a character at a given index in a String. It doesn't work. You're hoping that
str.replace(str.charAt(i), replacement);
will replace the i'th character of str. As pointed out in the other (now deleted) answer, str.replace doesn't change str itself, so you'd need to write
str = str.replace(str.charAt(i), replacement);
But that doesn't work. The replace() method doesn't know what your index i is. It only knows what character to replace. And, as the javadoc for replace() says, it replaces all characters in the string. So suppose that str.charAt(i) is 'a', and you want to replace it with 'd'. This code would replace all a characters with d, including (1) those that you already replaced with a earlier in the loop, so that this will defeat the work you've already done; and (2) a characters that come after this one, which you want to replace with d, but this will fail because later in the loop you will see d and replace it with g.
So you can't use replace(). There are a number of ways to replace the i'th character of a string, including using substring():
str = str.substring(0, i) + replacement + str.substring(i + 1);
But there are better ways, if you are going to replace every character. One is to create a StringBuilder from str, use StringBuilder's setCharAt method to change characters at specified indexes, and then convert the StringBuilder back to a String at the end. You should be able to look at the javadoc to find out what methods to use.
More: After looking into this more, I see why it was returning all A's. This inner loop has an error:
for (int c =0; c < alphabetNormal.length(); c++) {
if (str.charAt(i) == alphabetNormal.charAt(c)) {
char replacement = alphabetShifted.charAt(c);
str.replace(str.charAt(i), replacement);
}
}
Suppose key is 1, and the current character is 'C'. Your inner loop will eventually find C in alphabetNormal; it finds the corresponding character in alphabetShifted, which is D, and replaces C with D.
But then it loops back. Since the next character in alphabetNormal is D, it now matches the new str.char(i), which is now D, and therefore changes it again, to E. Then it loops back, and ... you get the picture.
replace below line
str.replace(str.charAt(i), replacement);
With
str= str.replace(str.charAt(i), replacement);
or you can make a String arr and then replace character in that. in the end create a new string from that array and return.
a better version of caesarify():
public static String caesarify(String str, int key){
String alphabetNormal = shiftAlphabet(0);
String alphabetShifted = shiftAlphabet(key);
//create a char array
char[] arr=str.toCharArray();
//always try to create variable outside of loop
char replacement
for (int i =0; i < arr.length();i++){
for (int c =0; c < alphabetNormal.length(); c++) {
if (arr[i] == alphabetNormal.charAt(c)) {
replacement = alphabetShifted.charAt(c);
//replace char on specific position in the array
arr[i]= replacement;
}
}
}
//return arrray as String
return new String(arr);
}

Java String. Replace list of chars by other chars list

I have String variable with value- f.e.:
this is test-str-ing_łóśżćń.
And I would like replace this chars:
, -, ł,ó,ś,ż,ć,ń
with those:
_,_,l,o,s,z,c,n.
And I mean here, that if parser will found f.e.: char - (which is second in first list) should be replaced with char that is in the same position/place in second list, which in this example is: _.
The char ó should be replaced with char o.
The char ń should be replaced with char n.
In my case the list of characters to replace is quite long and parsing in loop for each char to replace would not be enought efficient.
I know method replaceAll(). but it only accept one in String and one out String
So I am looking for method, that will allow me to work on arrays/list of Strings instead of single String.
Please give me some help.
Use java.text.Normalizer to Decompose accented letters in base letter plus "combining diacritical marks."
String base = Normalizer.normalize(accented, Form.NFKD)
.replaceAll("\\p{M}", "");
This does a decompose (D) normalization, and then removes Marks.
Some replacements still needed.
char[] out = new char[src.length()];
for( j ...){
inputChar = src.charAt(j);
for (int i = 0; i < convertChars.length; i++) {
if (inputChar == convertChars[i]) {
inputChar = toChars[i];
}
}
}
out[j] = inputChar ;
}
out2 = new String(out);
Extracted from bigger code without IDE, not tested. Loop (I hope) don't allocate objects and should not degrade speed.
Make a static lookup table:
private static char[] substitutions = new char[65536];
static {
// Initialize
for (char c = 0; c < substitutions.length; c++) {
substitutions[c] = c;
}
// Now add mappings.
substitions['-'] = '_'; // Map source->target character
... // Add the rest
}
// LATER IN Code
char[] stringChars = inputString.toCharArray();
for (int i = 0; i < stringChars.length; i++) {
stringChars[i] = substitutions[stringChars[i]];
}
outputString = new String(stringChars);

Filter bad words | java 'replace'

In an attempt to filter the bad words, I found the 'replace' function in java is not as handy as intended.
Please find below the code :
Eg : consider the word 'abcde' and i want to filter it to 'a***e'.
String test = "abcde";
for (int i = 1; i < sdf.length() - 1; i++) {
test= test.replace(test.charAt(i), '*');
}
System.out.print(test);
Output : a***e
But if the String is String test = "bbcde";, the output is ****e. It seems, if the word has repetitive letters(as in here), the replace function replaces the repetitive letters
too.
Why is it so? I want to filter the words excluding the first and last letter.
That is because String.replace(char, char) replaces all occurrences of the first character (according to its Javadoc).
What you want is probably more like this:
char[] word = test.toCharArray();
for (int i = 1; i < word.lengh - 1; i++) { // make sure to start at second char, and end at one-but-last char
word[i] = '*';
}
System.out.println(String.copyValueOf(word));
since String.replace(char, char) replaces all occurrences of specified char, this would be a better approach for your requirement:
String test = "abcde";
String replacement = "";
for (int i = 0; i < sdf.length(); i++) {
replacement += "*";
}
test= test.replace(sdf, replacement );
System.out.print(test);
It seems, if the word has repetitive letters(as in here), the replace function replaces the repetitive letters too. Why is it so?
Why? Because that's just how it works, exactly as the API documentation of String.replace(char oldChar, char newChar) says:
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
If you just want to replace the content of the string by the first letter, some asterisks and the last letter, then you don't need to use replace at all.
String test = "abcde";
if (test.length() >= 1) {
StringBuilder result = new StringBuilder();
result.append(test.charAt(0));
for (int i = 0; i < test.length() - 2; ++i) {
result.append('*');
}
result.append(test.charAt(test.length() - 1));
test = result.toString();
}
System.out.println(test);
public static void main(String[] args) {
String test = "bbcde";
String output = String.valueOf(test.charAt(0));
for (int i = 1; i < test.length() - 1; i++) {
output = output + "*";
}
output = output + String.valueOf(test.charAt(test.length() - 1));
System.out.print(output);
}
You should use the replaceAll-Function:
Link
With this you can replace all times you find a given substring in a string (f.e. "abcde") and replace all these with another string (f.e. "a***e").
String test = "abcde";
String replacement = "";
for (int i = 0; i < test.length(); i++) {
if (i==0 || i==test.length()-1){
replacement += test.charAt(i);
} else {
replacement += "*";
}
}
sdf = sdf.replaceAll(test, replacement);
System.out.print(test);

Java Stringbuilder.replace

Consider the following inputs:
String[] input = {"a9", "aa9", "a9a9", "99a99a"};
What would be the most efficient way whilst using a StringBuilder to replace any digit directly prior to a nine with the next letter after it in the alphabet?
After processing these inputs the output should be:
String[] output = {"b9", "ab9", "b9b9", "99b99a"}
I've been scratching my head for a while and the StringBuilder.setCharAt was the best method I could think of.
Any advice or suggestions would be appreciated.
Since you have to look at every character, you'll never perform better than linear in the size of the buffer. So you can just do something like
for (int i=1; buffer.length() ++i) // Note this starts at "1"
if (buffer.charAt[i] == '9')
buffer.setCharAt(i-1, buffer.getCharAt(i-1) + 1);
You can following code:
String[] input = {"a9", "aa9", "a9a9", "99a99a", "z9", "aZ9"};
String[] output = new String[input.length];
Pattern pt = Pattern.compile("([a-z])(?=9)", Pattern.CASE_INSENSITIVE);
for (int i=0; i<input.length; i++) {
Matcher mt = pt.matcher(input[i]);
StringBuffer sb = new StringBuffer();
while (mt.find()) {
char ch = mt.group(1).charAt(0);
if (ch == 'z') ch = 'a';
else if (ch == 'Z') ch = 'A';
else ch++;
mt.appendReplacement(sb, String.valueOf(ch));
}
mt.appendTail(sb);
output[i] = sb.toString();
}
System.out.println(Arrays.toString(output));
OUTPUT:
[b9, ab9, b9b9, 99b99a, a9, aA9]
You want to use a very simple state machine. For each character you're looping through in the input string, keep track of a boolean. If the character is a 9, set the boolean to true. If the character is a letter add one to the letter and set the boolean to false. Then add the character to the output stringbuilder.
For input you use a Reader. For output use a StringBuilder.
Use a 1 token look ahead parser technique. Here is some psuedoish code:
for (int index = 0; index < buffer.length(); ++index)
{
if (index < buffer.length() - 1)
{
if (buffer.charAt(index + 1) == '9')
{
char current = buffer.charAt(index) + 1; // this is probably not the best technique for this.
buffer.setCharAt(index, current);
}
}
}
another solution is for example to use
StringUtils.indexOf(String str, char searchChar, int startPos)
in a way as Ernest Friedman-Hill pointed, take this as experimental example, not the most performant

Add spaces between the characters of a string in Java?

I just want to add a space between each character of a string. Can anyone help me figuring out how to do this?
E.g. given "JAYARAM", I need "J A Y A R A M" as the result.
Unless you want to loop through the string and do it "manually" you could solve it like this:
yourString.replace("", " ").trim()
This replaces all "empty substrings" with a space, and then trims off the leading / trailing spaces.
ideone.com demonstration
An alternative solution using regular expressions:
yourString.replaceAll(".(?=.)", "$0 ")
Basically it says "Replace all characters (except the last one) with with the character itself followed by a space".
ideone.com demonstration
Documentation of...
String.replaceAll (including the $0 syntax)
The positive look ahead (i.e., the (?=.) syntax)
StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
if (i > 0) {
result.append(" ");
}
result.append(input.charAt(i));
}
System.out.println(result.toString());
Iterate over the characters of the String and while storing in a new array/string you can append one space before appending each character.
Something like this :
StringBuilder result = new StringBuilder();
for(int i = 0 ; i < str.length(); i++)
{
result = result.append(str.charAt(i));
if(i == str.length()-1)
break;
result = result.append(' ');
}
return (result.toString());
Blow up your String into array of chars, loop over the char array and create a new string by succeeding a char by a space.
Create a StringBuilder with the string and use one of its insert overloaded method:
StringBuilder sb = new StringBuilder("JAYARAM");
for (int i=1; i<sb.length(); i+=2)
sb.insert(i, ' ');
System.out.println(sb.toString());
The above prints:
J A Y A R A M
This would work for inserting any character any particular position in your String.
public static String insertCharacterForEveryNDistance(int distance, String original, char c){
StringBuilder sb = new StringBuilder();
char[] charArrayOfOriginal = original.toCharArray();
for(int ch = 0 ; ch < charArrayOfOriginal.length ; ch++){
if(ch % distance == 0)
sb.append(c).append(charArrayOfOriginal[ch]);
else
sb.append(charArrayOfOriginal[ch]);
}
return sb.toString();
}
Then call it like this
String result = InsertSpaces.insertCharacterForEveryNDistance(1, "5434567845678965", ' ');
System.out.println(result);
I am creating a java method for this purpose with dynamic character
public String insertSpace(String myString,int indexno,char myChar){
myString=myString.substring(0, indexno)+ myChar+myString.substring(indexno);
System.out.println(myString);
return myString;
}
This is the same problem as joining together an array with commas. This version correctly produces spaces only between characters, and avoids an unnecessary branch within the loop:
String input = "Hello";
StringBuilder result = new StringBuilder();
if (input.length() > 0) {
result.append(input.charAt(0));
for (int i = 1; i < input.length(); i++) {
result.append(" ");
result.append(input.charAt(i));
}
}
public static void main(String[] args) {
String name = "Harendra";
System.out.println(String.valueOf(name).replaceAll(".(?!$)", "$0 "));
System.out.println(String.valueOf(name).replaceAll(".", "$0 "));
}
This gives output as following use any of the above:
H a r e n d r a
H a r e n d r a
One can use streams with java 8:
String input = "JAYARAM";
input.toString().chars()
.mapToObj(c -> (char) c + " ")
.collect(Collectors.joining())
.trim();
// result: J A Y A R A M
A simple way can be to split the string on each character and join the parts using space as the delimiter.
Demo:
public class Main {
public static void main(String[] args) {
String s = "JAYARAM";
s = String.join(" ", s.split(""));
System.out.println(s);
}
}
Output:
J A Y A R A M
ONLINE DEMO
Create a char array from your string
Loop through the array, adding a space +" " after each item in the array(except the last one, maybe)
BOOM...done!!
If you use a stringbuilder, it would be efficient to initalize the length when you create the object. Length is going to be 2*lengthofString-1.
Or creating a char array and converting it back to the string would yield the same result.
Aand when you write some code please be sure that you write a few test cases as well, it will make your solution complete.
I believe what he was looking for was mime code carrier return type code such as %0D%0A (for a Return or line break)
and
\u00A0 (for spacing)
or alternatively
$#032

Categories

Resources