How to start replacing characters at some point? - java

It was very hard to form the question and I am sure it is still not clear.
I have a CSV file e.g.: Firstname;Lastname;Adress;product1;product2;product3;product4;
I would like to start replacing ";" with "::". The problem is, I want to start replacing after third semicolon.
I know it can be done in while loop where I check every character, when semicolon occurs I will count +1 and if counter is 3, I will start replacing. But isn't there a way how to do it without a loop?

You can use indexOf(char,fromIndex) method.
Your third semicolon position search can be inlined :
csvLine.indexOf(';', csvLine.indexOf(';', csvLine.indexOf(';') + 1) + 1)
We assume that our csvLine has a least 3 semi-colons...
String csvLine = "Firstname;Lastname;Adress;product1;product2;product3;product4";
//Index of "fromIndex" param is inclusive, that's why we need to add 1
int pos = csvLine.indexOf(';', csvLine.indexOf(';', csvLine.indexOf(';') + 1) + 1);
//Retrieve string from the char after the third semi-colon
String truncatedLine = csvLine.substring(pos + 1);
//Replace ";" by "::" on our substring
truncatedLine = truncatedLine.replaceAll(";", "::");
//Then concat the first part of csvLine with the second
String result = csvLine.substring(0, pos + 1).concat(truncatedLine);
System.out.println(result); //Print => Firstname;Lastname;Adress;product1::product2::product3::product4
Poor input control and performance but we don't have any loops :)

If I have understood what you want, try this.
First search se position of the third semicolon:
String csvContent = "Firstname;Lastname;Adress;product1;product2;product3;product4;";
int i = 0;
int index= 0;
while(i < 4){
index = csvContent.indexOf(';', (index + 1));
i++;
}//index = position of the thrid semicolon
Second, cut your CSV content at the index position.
String tmp1 = csvContent.substring(0, index);
String tmp2 = csvContent.substring(index, csvContent.length());
Thrid, replace all ';' by '::':
tmp2 = tmp2.replaceAll(";", "::");
Finaly, rebuild your file content:
csvContent = tmp1 + tmp2;

int i = 0;
int pos = 0;
while (i < 3) {
pos = string.indexOf(';', pos+1);
i++;
}
String newString = string.substring(0, pos) +";"+ (string.substring(pos + 1, string.length()).replace(";", "::"));

how about a regex solution?
Pattern pattern = Pattern.compile("(.*?;.*?;.*?;)(.*)");
Matcher match = pattern.matcher(str);
if(match.matches()) {
String firstThree = match.group(1);
String rest = match.group(2);
rest = rest.replace(";", "::");
return firstThree + rest;
}

Related

Java: How to fix "String index out of range: #"? [duplicate]

This question already has answers here:
Java substring: 'string index out of range'
(13 answers)
Closed 3 years ago.
I'm attempting to scramble two random letters of a string which isn't the first letter, or last two. I'm getting a "String index out of range" error when compiling. I've tried workshopping many different solutions, but nothing seems to work.
For this assignment, we have to use a method and .charAt commands. I've tried creating variables for the two random characters then adding them back into the string flipped, but couldn't get that to work either.
public static String scramble(String input) {
int range = input.length() - 3;
int place = (int)(Math.random() * range);
String newWord = "";
newWord = input.substring(0, place);
newWord = newWord + newWord.charAt(place) + 2;
newWord = newWord + newWord.charAt(place) + 1;
return newWord;
I'm expecting an output of a string with two of its characters scrambled. For example, "Fantastic" would be "Fantsatic", or "Fnatastic".
Try something like this:
public static String scramble(String input) {
int range = input.length() - 3;
int place = (int)(Math.random() * range);
String newWord = input.substring(0, place);
newWord = newWord + input.charAt(place + 1);
newWord = newWord + input.charAt(place);
// if you need the whole input, just 2 characters exchanged, uncomment this next line
// newWord = newWord + input.substring(place + 2, range);
return newWord;
}
You do :
newWord = input.substring(0, place);
So the indexes inside newWord goes from 0 to place-1
Then you do:
newWord.charAt(place);
But this index does not exist in your String. It is Out of Bound
See the doc
When you create newWord = input.substring(0, place) it has exactly place characters. You can't request charAt(place) from it, the last character is at place-1.
If you want to swap characters convert input to char[] and generate random indexes to swap.
String input = "Fantastic";
// random constraints
int min = 1;
int max = input.length() - 3;
// random two characters to swap
int from = min + (int) (Math.random() * max);
int to;
do {
to = min + (int) (Math.random() * max);
} while (to == from); // to and from are different
// swap to and from in chars
char[] chars = input.toCharArray();
char tmp = chars[from];
chars[from] = chars[to];
chars[to] = tmp;
String result = new String(chars);
System.out.println(result); // Ftntasaic
you can try
public static String scramble(String input) {
if(input.length() >3){
int range = input.length() - 3;
int place = 1+ new Random().nextInt(range) ;
input=input.substring(0, place) +input.charAt(place + 1)+input.charAt(place) +input.substring( place+2);
}
return input;
}
input: Fantastic
output : Fanatstic , Fatnastic ,Fanatstic

Insert a String into an other String

How can i add a line of String into the main String. The main String contains multiple lines of text. I want to add a new line to the third line and push backwards the rest of the main String.
Direct concatenation is the simplest way to write this:
string = string.substring(0, position) + newData + string.substring(position);
where position is the location at which you want to insert the data, found e.g. using indexOf:
int position = -1;
for (int i = 0; i < 3; ++i) {
position = string.indexOf('\n', position + 1);
}
An alternative to direct concatenation:
string = new StringBuilder(string)
.insert(position, newData)
.toString();
Or (perhaps more efficient):
string = new StringBuilder(string.length() + newData.length())
.append(string, 0, position)
.append(newData)
.append(string, position, string.length())
.toString();
Split into a list, insert into list, then join list.
List<String> lines = new ArrayList(string.split('\n'))
lines.add(2, newLine)
String newString = lines.join('\n')
or
Get the position of the 3rd line, then use substring
string.substring(0, insertPos) + '\n' + newString + string.substring(insertPos, string.length())
You may use String.format.
String main = "line1\nline2\n%sline4";
String sub = "line3\n";
String result = String.format(main, sub);

Get index of 3rd comma

For example I have this string params: Blabla,1,Yooooooo,Stackoverflow,foo,chinese
And I want to get the string testCaseParams until the 3rd comma: Blabla,1,Yooooooo
and then remove it and the comma from the original string so I get thisStackoverflow,foo,chinese
I'm trying this code but testCaseParams only shows the first two values (gets index of the 2nd comma, not 3rd...)
//Get how many parameters this test case has and group the parameters
int amountOfInputs = 3;
int index = params.indexOf(',', params.indexOf(',') + amountOfInputs);
String testCaseParams = params.substring(0,index);
params = params.replace(testCaseParams + ",","");
You can hold the index of the currently-found comma in a variable and iterate until the third comma is found:
int index = 0;
for (int i=0; i<3; i++) index = str.indexOf(',', index);
String left = str.substring(0, index);
String right = str.substring(index+1); // skip comma
Edit: to validate the string, simply check if index == -1. If so, there are not 3 commas in the string.
One option would be a clever use of String#split:
String input = "Blabla,1,Yooooooo,Stackoverflow,foo,chinese";
String[] parts = input.split("(?=,)");
String output = parts[0] + parts[1] + parts[2];
System.out.println(output);
Demo
One can use split with a limit of 4.
String input = "Blabla,1,Yooooooo,Stackoverflow,foo,chinese";
String[] parts = input.split(",", 4);
if (parts.length == 4) {
String first = parts[0] + "," + parts[1] + "," + parts[2];
String second = parts[3]; // "Stackoverflow,foo,chinese"
}
You can split with this regex to get the 2 pats:
String[] parts = input.split("(?<=\\G.*,.*,.*),");
It will result in parts equal to:
{ "Blabla,1,Yooooooo", "Stackoverflow,foo,chinese" }
\\G refers to the previous match or the start of the string.
(?<=) is positive look-behind.
So it means match a comma for splitting, if it is preceded by 2 other commas since the previous match or the start of the string.
This will keep empty strings between commas.
I offer this here just as a "fun" one line solution:
public static int nthIndexOf(String str, String c, int n) {
return str.length() - str.replace(c, "").length() < n ? -1 : n == 1 ? str.indexOf(c) : c.length() + str.indexOf(c) + nthIndexOf(str.substring(str.indexOf(c) + c.length()), c, n - 1);
}
//Usage
System.out.println(nthIndexOf("Blabla,1,Yooooooo,Stackoverflow,foo,chinese", ",", 3)); //17
(It's recursive of course, so will blow up on large strings, it's relatively slow, and certainly isn't a sensible way to do this in production.)
As a more sensbile one liner using a library, you can use Apache commons ordinalIndexOf(), which achieves the same thing in a more sensible way!

Java - Reverse String null error

The input is meant to appear like this, example.
\n
Kazan R
\n
6789
\n
Nzk462
\n
However the output I receive looks like this
kzn462nullnzk
Why is this? and How can i solve it?
private void btnGenerateActionPerformed(java.awt.event.ActionEvent evt) {
secondname = JOptionPane.showInputDialog("Enter your surname:");
firstname = JOptionPane.showInputDialog("Enter your firstname:");
idno = JOptionPane.showInputDialog("Enter your idno:");
nametag = firstname.substring(0, 1);
initials = secondname + " " + nametag;
int randnum;
do {
randnum = (int) (Math.random() * 900) + 100;
} while (randnum % 2 != 0);
code = secondname.replaceAll("[aeiou || AEIOU](?!\\b)", "")+randnum ;
txaDisplay.append(initials + '\n' + idno.substring(6,10) + '\n' + code);
int length = secondname.length();
for (int i = length - 1; i >= 0; i--) {
reverse = reverse + secondname.charAt(i);
}
String end = reverse + code;
txaDisplay.append( reverse);
Why don't you use
new StringBuilder(secondname).reverse().toString()
to reverse your String? It's better, simple and more maintanable.
Get the character array from your source string
Create a new char array of same length
Start iterating from 0 to (sourceStringLength-1)
In each iteration, get the last character
from the end in your source array and populate in your new array
Create a new string from this new array
String source = "abcdefg";
char[] chars = source.toCharArray();
char[] reverseChars = new char[source.length()];
int len = source.length();
for(int i= 0; i < len; i++){
reverseChars[i] = chars[len-1-i];
}
String reverse = new String(reverseChars);
System.out.println(reverse);
Since You don't want to use StringBuilder/StringBuffer.
Try this
String reversedString="";
for(int i=inputString.length-1;i>=0;){
reversedString+=inputString.charAt(i--);
}
I think the problem is your definition of reverse, maybe you have something like:
String reverse;
Then you don't initialize your "reverse" so when your program makes the first concatenation in your loop, it looks like this:
reverse = null + secondname.charAt(i);
The null value is converted to a string so it can be visible in the output.
I hope this information helps you.
Good Luck.

Find the last index of the first match in Java

Lets say I have this string
String s ="stackjomvammssastackvmlmvlrstack"
And I want to find the last index of the first match of the substring "stack" which is (index=)4 in my example.
How will I do that?
Here's what I have done so far
Matcher m = pattern.matcher(s);
int i=0;
while (m.find())
{
System.out.println(m.start());
System.out.println(m.end());
}
But that displays the last index of the last match.
You can simply find the position of the word and add its length:
String s = "stackjomvammssastackvmlmvlrstack";
String match = "stack";
int start = s.indexOf(match);
int end = (start + match.length() - 1);
System.out.println(match + " found at index " + start);
System.out.println("Index of last character of first match is " + end);
If you need to use a regex, your code is close to the solution - you could do this:
String s = "stackjomvammssastackvmlmvlrstack";
String match = "s.*?k";
Matcher m = Pattern.compile(match).matcher(s);
if (m.find()) {
System.out.println(m.end() - 1);
}
try this code:
if (m.find())
System.out.println(m.end() - 1);
from java doc of Matcher.end():
Returns the offset after the last character matched.
If I understood your question right, you are trying to find the first match of "stack", and then get the last index....
You can accomplish this by doing:
string toFind = "stack";
int firstOccurance = s.indexOf(toFind); (being s the word you posted above)
int whatYourLooking = firstOccurance + toFind.length() - 1;
Hope it helps! ;)
This way?
String s ="stackjomvammssastackvmlmvlrstack";
String word = "stack";
int index = s.indexOf(word) + word.length() - 1;
final String input = "stackjomvammssastackvmlmvlrstack";
final String stack = "stack";
int start = input.indexOf(stack);
int end = start + stack.length() - 1;
String s = "stackjomvammssastackvmlmvlrstack";
String stack = "stack";
int index = s.indexOf(stack) + stack.length();
im edited my previous answer
String s ="stackjomvammssastackvmlmvlrstack";
String pattern = "stack";
Matcher m = pattern.matcher(s);
int i=0;
while (m.find())
{
System.out.println(m.start());
System.out.println(m.start()+m.length());
}

Categories

Resources