Related
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!
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;
}
How would I replace a string 10100 with 10010 using the algorithm "replace the last substring 10 with 01."
I tried
s=s.replace(s.substring(a,a+2), "01");
but this returns 01010, replacing both the first and the second substring of "10".
"a" represents s.lastindexOf("10");
Here's a simple and extensible function you can use. First its use/output and then its code.
String original = "10100";
String toFind = "10";
String toReplace = "01";
int ocurrence = 2;
String replaced = replaceNthOcurrence(original, toFind, toReplace, ocurrence);
System.out.println(replaced); // Output: "10010"
original = "This and This and This";
toFind = "This";
toReplace = "That";
ocurrence = 3;
replaced = replaceNthOcurrence(original, toFind, toReplace, ocurrence);
System.out.println(replaced); // Output: "This and This and That"
Function code:
public static String replaceNthOcurrence(String str, String toFind, String toReplace, int ocurrence) {
Pattern p = Pattern.compile(Pattern.quote(toFind));
Matcher m = p.matcher(str);
StringBuffer sb = new StringBuffer(str);
int i = 0;
while (m.find()) {
if (++i == ocurrence) { sb.replace(m.start(), m.end(), toReplace); break; }
}
return sb.toString();
}
If you want to access the last two indices of a string, then you can use: -
str.substring(str.length() - 2);
This gives you string from index str.length() - 2 to the last character, which is exactly the last two character.
Now, you can replace the last two indices with whatever string you want.
UPDATE: -
Of you want to access the last occurrence of a character or substring, you can use String#lastIndexOf method: -
str.lastIndexOf("10");
Ok, you can try this code: -
String str = "10100";
int fromIndex = str.lastIndexOf("10");
str = str.substring(0, fromIndex) + "01" + str.substring(fromIndex + 2);
System.out.println(str);
10100 with 10010
String result = "10100".substring(0, 2) + "10010".substring(2, 4) + "10100".substring(4, 5);
You can get the last index of a character or substring using string's lastIndexOf method. See the documentation link below for how to use it.
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#lastIndexOf(java.lang.String)
Once you know the index of your substring, you can get the substring of all characters before that index, and the substring of all characters after the last character in your search string, and concatenate.
This is a little drawn out, and I didn't actually run it (so I might have a syntax error), but it gives you the point of what I'm trying to convey at least. You could do this all in one line if you want, but it wouldn't illustrate the point as well.
string s = "10100";
string searchString = "10";
string replacementString = "01";
string charsBeforeSearchString = s.substring(0, s.lastIndexOf(searchString) - 1);
string charsAfterSearchString = s.substring(s.lastIndexIf(searchString) + 2);
s = charsBeforeSearchString + replacementString + charsAfterSearchString;
The easiest way:
String input = "10100";
String result = Pattern.compile("(10)(?!.*10.*)").matcher(input).replaceAll("01");
System.out.println(result);
String str = "AlwinX-road-9:00pm-kanchana travels-25365445421";
String[] names = str.split("-");
I want output like following:
AlwinX-road
9:00pm
kanchana travels
25365445421
Use pattern matching to match your requirement
String str = "AlwinX-road-9:00pm-kanchana travels-25365445421";
String regex = "(^[A-Z-a-z ]+)[-]+(\\d+:\\d+pm)[-]([a-z]+\\s+[a-z]+)[-](\\d+)";
Matcher matcher = Pattern.compile( regex ).matcher( str);
while (matcher.find( ))
{
String roadname = matcher.group(1);
String time = matcher.group(2);
String travels = matcher.group(3);
String digits= matcher.group(4);
System.out.println("time="+time);
System.out.println("travels="+travels);
System.out.println("digits="+digits);
}
Since you want to include the delimiter in your first output line, you can do the split, and merge the first two element with a -: -
String[] names = str.split("-");
System.out.println(names[0] + "-" + names[1])
for (int i = 2;i < names.length; i++) {
System.out.println(names[i])
}
The split() method can't distinguish the dash in AlwinX-road and the other dashes in the string, it treats all the dashes the same. You will need to do some sort of post processing on the resulting array. If you will always need the first two strings in the array joined you can just do that. If your strings are more complex you will need to add additional logic to join the strings in the array.
One way you could do it, assuming the first '-' is always part of a two part identifier.
String str = "AlwinX-road-9:00pm-kanchana travels-25365445421";
String[] tokens = str.split("-");
String[] output = new String[tokens.length - 1];
output[0] = tokens[0] + '-' + tokens[1];
System.out.println(output[0]);
for(int i = 1; i < output.length; i++){
output[i] = tokens[i+1];
System.out.println(output[i]);
}
Looks like you want to split (with removal of all dashes but the first one).
String str = "AlwinX-road-9:00pm-kanchana travels-25365445421";
String[] names = str.split("-");
for (String value : names)
{
System.out.println(value);
}
So its produces:
AlwinX
road
9:00pm
kanchana travels
25365445421
Notice that "AlwinX" and "road" we split as well since they had a dash in between. So you will need custom logic to handle this case. here is an example how to do it (I used StringTokenizer):
StringTokenizer tk = new StringTokenizer(str, "-", true);
String firstString = null;
String secondString = null;
while (tk.hasMoreTokens())
{
final String token = tk.nextToken();
if (firstString == null)
{
firstString = token;
continue;
}
if (secondString == null && firstString != null && !token.equals("-"))
{
secondString = token;
System.out.println(firstString + "-" + secondString);
continue;
}
if (!token.equals("-"))
{
System.out.println(token);
}
}
This will produce:
AlwinX-road
9:00pm
kanchana travels
25365445421
from your format, I think you want to split the first one just before the time part. You can do it this way:
String str =yourString;
String beforetime=str.split("-\\d+:\\d+[ap]m")[0]; //this is your first token,
//AlwinX-road in your example
String rest=str.substring(beforetime.length()+1);
String[] restNames=rest.split("-");
If you really need it all together in one array then see the code below:
String[] allTogether=new String[restNames.length+1];//the string with all your tokens
allTogether[0]=beforetime;
System.arraycopy(restNames, 0, allTogether, 1, restNames.length);
If you use "_" as a separator instead of "-": AlwinX-road_9:00pm_kanchana travels_25365445421
New code:
String str = new String("AlwinX-road_9:00pm_kanchana travels_25365445421");
String separator = new String("_");
String[] names = str.split(separator);
for(int i=0; i<names.length; i++){
System.out.println(names[i]);
}
I am trying to split a string into 29 tokens..... stringtokenizer won't return null tokens. I tried string.split, but I believe I am doing something wrong:
String [] strings = line.split(",", 29);
sample inputs:
10150,15:58,23:58,16:00,00:00,15:55,23:55,15:58,00:01,16:03,23:58,,,,,16:00,23:22,15:54,00:03,15:59,23:56,16:05,23:59,15:55,00:01,,,,
10155,,,,,,,,,,,07:30,13:27,07:25,13:45,,,,,,,,,,,07:13,14:37,08:01,15:23
10160,10:00,16:02,09:55,16:03,10:06,15:58,09:48,16:07,09:55,16:00,,,,,09:49,15:38,10:02,16:04,10:00,16:00,09:58,16:01,09:57,15:58,,,,
If you want the trailing empty strings to be kept, but you don't want to give a magic number for maximum, use a negative limit:
line.split(",", -1)
If line.equals("a,,c"), then line.split(",", -1)[1].isEmpty(); it's not null. This is because when "," is the delimiter, then ",," has an empty string between the two delimiters, not null.
Example:
Using the explanation above, consider the following example: ",,"
Although you might expect ",", null, and ",".
The actual result is ",", "" and ","
If you want null instead of empty strings in the array returned by split, then you'd have to manually scan the array and replace them with null. I'm not sure why s == null is better than s.isEmpty(), though.
See also
Java String.indexOf and empty strings
Use StringUtils.splitPreserveAllTokens() in Apache Commons Lang library
If you want empty tokens to be retained string.split won't work satisfactorily. StringTokenizer will also no work.
I have come with following method, which might be helpful for you
public static String[] splitTotokens(String line, String delim){
String s = line;
int i = 0;
while (s.contains(delim)) {
s = s.substring(s.indexOf(delim) + delim.length());
i++;
}
String token = null;
String remainder = null;
String[] tokens = new String[i];
for (int j = 0; j < i; j++) {
token = line.substring(0, line.indexOf(delim));
//System.out.print("#" + token + "#");
tokens[j] = token;
remainder = line.substring(line.indexOf(delim) + delim.length());
//System.out.println("#" + remainder + "#");
line = remainder;
}
return tokens;`
}
use this org.springframework.util.StringUtils
org.springframework.util.StringUtils.delimitedListToStringArray(data, delimit);
This class delivers some simple functionality provides easy-to-use methods to convert between delimited strings, such as CSV strings, and collections and arrays.
If you want empty tokens to be retained string.split() won't work satisfactorily. StringTokenizer will also not work. I have come with following method, which might be helpful for you:
public static String[] splitTotokens(String line, String delim){
String s = line;
int i = 0;
while (s.contains(delim)) {
s = s.substring(s.indexOf(delim) + delim.length());
i++;
}
String token = null;
String remainder = null;
String[] tokens = new String[i];
for (int j = 0; j < i; j++) {
token = line.substring(0, line.indexOf(delim));
// System.out.print("#" + token + "#");
tokens[j] = token;
remainder = line.substring(line.indexOf(delim) + delim.length());
//System.out.println("#" + remainder + "#");
line = remainder;
}
return tokens;
}