Liwaa
Liwaa

Reputation: 45

Getting a String between 2 words

I want to get the string between 2 words in a string. like so:

String s = "Play A ROCK song"

So I want to get the string between: A and song, which in this case is rock.

I tried this:

    public static String subStringBetween(String text, String after, String before) {
    String p1 = getWordsAfter(text, after);
    String p2 = getWordsBefore(text, before);

    Set<String> aSet = new HashSet<>(Arrays.asList(p1.split(" ")));
    Set<String> bSet = new HashSet<>(Arrays.asList(p2.split(" ")));

    Set<String> result = new HashSet<>(aSet);
    result.retainAll( bSet);
    String string = "";
    for (String s : result) {
        if (string == "") {
            string = s;
        }else{
            string +=" " + s;
        }
    }
    return string;
}

public static String getWordsAfter(String text, String word) {
    String[] splt = text.split(word);
    return splt[1];
}

public static String getWordsBefore(String text, String word) {
    String[] splt = text.split(word);
    return splt[0];
}

It works, but If the string between A and Song is more than one word, it works, but prints something weird, like if it was: Play a Nice Rock Song the return would be Rock Nice, not Nice Rock

Upvotes: 1

Views: 1500

Answers (2)

Planck Constant
Planck Constant

Reputation: 1524

You can also try a little bit shorter code:

public static String subStringBetween(String text, String after, String before) {
    Pattern pattern = Pattern.compile("(?<=\\s|^)"+after +"\\s(.*?)\\s+"+ before);
    Matcher matcher = pattern.matcher(text);

    while (matcher.find()) {
        return matcher.group(1);
    }
    return ""; //or null or whatever you need

}

Input: Play a Nice Rock Song 
After: a 
Before: Song
Output: Nice Rock

Input: play a rock song xxx
After: a 
Before: song
Output: rock

Input: a Play Nice Rock Song
After: a 
Before: Song
Output: Play Nice Rock

Input: aaaa bbbb a bbb aaa b aaaa bbb
After: a 
Before: b
Output: bbb aaa

Upvotes: 1

Makoto
Makoto

Reputation: 106470

This is a very novel way of going about this, so I'll respect that and not suggest regular expressions (although that would be the more straightforward approach).

In this context, you've run into an issue: hash sets are not guaranteed to be in any specific order, and since you're iterating over them in a specific order, who knows what order those strings will come in?

The fix is actually very simple. Make use of the LinkedHashSet class instead. This is guaranteed to preserve insertion order.

Do this for all of the sets you're using.

Set<String> aSet = new LinkedHashSet<>(Arrays.asList(p1.split(" ")));
Set<String> bSet = new LinkedHashSet<>(Arrays.asList(p2.split(" ")));

Set<String> result = new LinkedHashSet<>(aSet);

Then, the order will be what you expect when you invoke your method.

Upvotes: 2

Related Questions