4
\$\begingroup\$

I am trying to implement a Java version sub-string extractor with "start keyword" and "end keyword" and the extracted result is from (but excluded) the given start keyword to (but excluded) end keyword. The output sub-string follows the rules as below.

  • The leading/trailing spaces in output sub-string is removed.
  • If the given start keyword is an empty string, it means that the anchor is at the start of the input string. Otherwise, the first occurrence of the given start keyword is an start anchor. If there is no any occurrence of the given start keyword, the output is an empty string.
  • If the given end keyword is an empty string, it means that the anchor is at the end of the input string. Otherwise, the first occurrence of the given end keyword is an end anchor. If there is no any occurrence of the given end keyword, the output is an empty string.
  • If the location of start anchor is after than the location of end anchor, or a part of the first occurrence of the given start keyword and a part of the first occurrence of the given end keyword are overlapped, the output is an empty string.

The example input and output is listed as below.

Input String Start Keyword End Keyword Output
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" ""(empty string) ""(empty string) "Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible"
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" ""(empty string) "dependencies" "Java is a class-based, object-oriented programming language that is designed to have as few implementation"
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "Java" ""(empty string) "is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible"
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "Java" "dependencies" "is a class-based, object-oriented programming language that is designed to have as few implementation"
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "dependencies" ""(empty string) "as possible"
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" ""(empty string) "Java" ""(empty string)
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "dependencies" "Java" ""(empty string)
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "ABC" "" ""(empty string)
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "" "XYZ" ""(empty string)
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "ABC" "XYZ" ""(empty string)
"Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible" "Java" "Java" ""(empty string)

The experimental implementation

The experimental implementation is as below.

private static String GetTargetString(String input, String startKeyword, String endKeyword)
{
    if (!input.isEmpty() && input.indexOf(startKeyword) < 0) return "";
    if (!input.isEmpty() && input.indexOf(endKeyword) < 0) return "";

    int startIndex = startKeyword.isEmpty()
            ? 0
            : input.indexOf(startKeyword) + startKeyword.length();

    int endIndex = endKeyword.isEmpty()
            ? input.length()
            : input.indexOf(endKeyword);

    if (startIndex < 0 || endIndex < 0 || startIndex >= endIndex) return "";

    return input.substring(startIndex, endIndex).trim();
}

Test cases

String testString1 = "Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible";

System.out.println(GetTargetString(testString1, "", ""));
System.out.println(GetTargetString(testString1, "", "dependencies"));
System.out.println(GetTargetString(testString1, "Java", ""));
System.out.println(GetTargetString(testString1, "Java", "dependencies"));
System.out.println(GetTargetString(testString1, "dependencies", ""));
System.out.println(GetTargetString(testString1, "", "Java"));
System.out.println(GetTargetString(testString1, "dependencies", "Java"));
System.out.println(GetTargetString(testString1, "ABC", ""));
System.out.println(GetTargetString(testString1, "", "XYZ"));
System.out.println(GetTargetString(testString1, "ABC", "XYZ"));
System.out.println(GetTargetString(testString1, "Java", "Java"));

The output of the above test cases.

Java is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible
Java is a class-based, object-oriented programming language that is designed to have as few implementation
is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible
is a class-based, object-oriented programming language that is designed to have as few implementation
as possible






Coding Ground Link

If there is any possible improvement, please let me know.

\$\endgroup\$
3
\$\begingroup\$

Holes

GetTargetString("Where the start is before here.", "start", "here"); will return "", which seems wrong! Expected result would be "is before".

  • Should "Where" be a match for the ending keyword "here"? They are not the same word, so it doesn't seem to be really a keyword based extraction function.
  • Perhaps you should look for the first ending keyword after the start, using input.indexOf(endKeyword, startIndex)? Or,
  • Perhaps you want the last keyword? Ie, input.lastIndexOf(endKeyword)

Code Review

Naming

In Java, class names generally begin with an uppercase letter, and have mixed case for the rest of the name. This makes GetTargetString look like a class name instead of a method name.

Repeated Work

input.indexOf(startKeyword) and input.indexOf(endKeyword) are called more than once. This is inefficient especially if the input is long and the word being searched for is short, or substrings of the needle occur often in the haystack.

Unnecessary Condition

The endIndex < 0 test is unnecessary. Since you have tested startIndex < 0, when you test startIndex >= endIndex, you will know that startIndex >= 0 so startIndex >= endIndex will always be true if endIndex < 0. That condition may safely be omitted.

\$\endgroup\$
1
\$\begingroup\$

Just one point additionally to AJNeufeld's great post:

You can avoid the duplicate indexOf() calls by simply removing the first two lines and checking startIndex < startKeyword.length() instead of startIndex < 0 later on.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.