The code below takes a string that potentially contains a true match for a delimiter. There can be multiple delimiters located anywhere in the string. We need to obtain the indices that are not a match and when the delimiter starts and ends. The following code achieves this. However, I am unsure if this is the most optimal method. What do you think? Test cases below the code.
String baseText = "%!ABCD%!EF%";
String delimiter = "%";
ArrayList<String> selectedParameters = new ArrayList<>();
int lastNonDelimited = 0;
int i = 0;
while (i < baseText.length()) {
int j = 0;
while (j < delimiter.length()) {
if (j + i == baseText.length() - 1 && j != delimiter.length() - 1) {
lastNonDelimited += 1;
System.out.println(lastNonDelimited);
break;
}
char c = baseText.charAt(i + j);
char d = delimiter.charAt(j);
if (c == d) {
if (j == delimiter.length() - 1) {
lastNonDelimited += delimiter.length();
i += (delimiter.length() - 1);
System.out.println("End" + (i + j));
} else {
System.out.println("Beginnning" + (i + j + 1));
}
} else {
lastNonDelimited += 1;
System.out.println(lastNonDelimited);
break;
}
j += 1;
}
i += 1;
}
Test case 1:
String %!ABCD%!EF% with %! delimiter results in:
Beginnning1
End2
3
4
5
6
Beginnning7
End8
9
10
11
Test case 2:
String %!ABCD%!EF%! with %! delimiter results in:
Beginnning1
End2
3
4
5
6
Beginnning7
End8
9
10
Beginnning11
End12
3 Answers 3
Some off the cuff comments:
It would help if you provided a compilable class rather than a somewhat misleading snippet.
Your search would be better as a separate method.
I don't see why you search in this way when String.indexof(String) and String.substring(int) exist.
Have you a clear understanding of how you would handle overlapping delimiters? If your delimiter is "!!", how is "abc!!!def" to be interpreted?
Looking at the code, I can't easily tell its purpose.
Java code exists in files and class
es, blocks, functions, methods, and lambdas.
With the exception of blocks, these can be named using telling names. There are conventions for "documentation" using doc comments.
The title mentions supporting greater than 1 length of delimiters:
Include tests with delimiter length 1, and greater than 2.
And a test with a proper prefix of the delimiter followed by more characters. And...
Rather than declaring and initialising a control variable like i
to be incremented after last use in a while
loop, use a for
loop.
If handling characters was the way to find delimiters (it isn't), this might look
/** Outputs each 1-based delimiter start and end index,
* and indexes of non-delimiter characters.
*/
static void
reportDelimiterAndNondelimiterIndexes_(String text, String delimiter) {
final int
length = text.length(),
delimiterLast = delimiter.length() - 1;
for (int i = 0 ; i < length ; ) {
boolean startsDelimiter = true;
for (int j = 0 ; j <= delimiterLast ; j++)
if (length <= i + j || text.charAt(i + j) != delimiter.charAt(j)) {
startsDelimiter = false;
break;
}
i += 1;
if (startsDelimiter) {
System.out.println(i + " Start");
i += delimiterLast;
System.out.println(i + " End");
} else
System.out.println(i);
}
}
// But startsDelimiter should not be reset in a loop
// given text.startsWith(delimiter, i):
/** Prints each 1-based delimiter start and end index,
* and indexes of non-delimiter characters to System.out.
*/
static void
reportDelimiterAndNondelimiterIndexes(String text, String delimiter) {
for (int i = 1 ; i <= text.length() ; i++)
if (text.startsWith(delimiter, i - 1)) {
System.out.println(i + " Start");
i += delimiter.length() - 1;
System.out.println(i + " End");
} else
System.out.println(i);
}
public static void main(String []args) {
String
tests[] = { "single", "lone single",
"multi complete", "multi incomplete", "lone multi" },
texts[] = { "'a'b''c'", "'", "«'»a«'»b«'»«'»c«'»", "«'a«'b«'", "«'»" },
delimiters[] = { "'", "'", "«'»", "«'»", "«'»" };
for (int i = 0 ; i < texts.length ; i++) {
System.out.println(tests[i] + ':');
reportDelimiterAndNondelimiterIndexes(texts[i], delimiters[i]);
}
}
Several speed improvements are apparent: Don't (without indication of a speed problem here).
Following code part can be changed. There is no use with in the code for char c & char d. Hence following code can be removed
char c = baseText.charAt(i + j);
char d = delimiter.charAt(j);
And if can be used like
if (baseText.charAt(i + j) == delimiter.charAt(j))
One More way to implement this could be like this, a bit more small and possible easy to manage.
{
String baseText = "%!ABCD%!EF%!";
String delimiter = "%!";
int i = 0;
int length = baseText.length();
String replaceMent = "";
while (i < length) {
if (i < baseText.indexOf(delimiter) || !baseText.contains(delimiter)) {
System.out.println(i + 1);
i++;
continue;
}
System.out.println("Beginning" + (baseText.indexOf(delimiter) + 1));
System.out.println("End" + (baseText.indexOf(delimiter) + delimiter.length()));
for (int j = 0; j < delimiter.length(); j++) {
if (replaceMent.length() == 0) {
replaceMent = " ";
} else {
replaceMent = replaceMent + " ";
}
}
baseText = baseText.replaceFirst(delimiter, replaceMent);
replaceMent = "";
i = i + delimiter.length();
}
}