membersound
membersound

Reputation: 86687

How to substring before nth occurence of a separator?

first;snd;3rd;4th;5th;6th;...

How can I split the above after the third occurence of the ; separator? Especially without having to value.split(";") the whole string as an array, as I won't need the values separated. Just the first part of the string up until nth occurence.

Desired output would be: first;snd;3rd. I just need that as a string substring, not as split separated values.

Upvotes: 6

Views: 2356

Answers (7)

The fourth bird
The fourth bird

Reputation: 163217

You could use a regex that uses a negated character class to match from the start of the string not a semicolon.

Then repeat a grouping structure 2 times that matches a semicolon followed by not a semicolon 1+ times.

^[^;]+(?:;[^;]+){2}

Explanation

  • ^ Assert the start of the string
  • [^;]+ Negated character class to match not a semicolon 1+ times
  • (?: Start non capturing group
  • ;[^;]+ Match a semicolon and 1+ times not a semi colon
  • ){2} Close non capturing group and repeat 2 times

For example:

String regex = "^[^;]+(?:;[^;]+){2}";
String string = "first;snd;3rd;4th;5th;6th;...";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);

if (matcher.find()) {
    System.out.println(matcher.group(0)); // first;snd;3rd
}

See the Java demo

Upvotes: 1

Rafał Sokalski
Rafał Sokalski

Reputation: 2007

Below code find index of 3rd occurence of ';' character and make substring.

String s = "first;snd;3rd;4th;5th;6th;";
String splitted = s.substring(0, s.indexOf(";", s.indexOf(";", s.indexOf(";") + 1) + 1));

Upvotes: 0

Conffusion
Conffusion

Reputation: 4465

If you need to do this frequently it is best to compile the regex upfront in a static Pattern instance:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NthOccurance {

    static Pattern pattern=Pattern.compile("^(([^;]*;){3}).*");

    public static void main(String[] args) {

        String in="first;snd;3rd;4th;5th;6th;";
        Matcher m=pattern.matcher(in);
        if (m.matches())
            System.out.println(m.group(1));
    }
}

Replace the '3' by the number of elements you want.

Upvotes: 0

rLevv
rLevv

Reputation: 508

If you want to use regular expressions, it is pretty straightforward:

import re
value = "first;snd;3rd;4th;5th;6th;"
reg = r'^([\w]+;[\w]+;[\w]+)'
re.match(reg, value).group()

Outputs:

"first;snd;3rd"

More options here .

Upvotes: 2

alain.janinm
alain.janinm

Reputation: 20065

If you don't want to use split, just use indexOf in a for loop to know the index of the 3rd and 4th ";" then do a substring between these index.

Also you can do a split with a regex that match the 3rd ; but it's probably not the best solution.

Upvotes: 0

Leviand
Leviand

Reputation: 2805

I would go with this, easy and basic:

String test = "first;snd;3rd;4th;5th;6th;";
int result = 0;
for (int i = 0; i < 3; i++) {
    result = test.indexOf(";", result) +1;
}

System.out.println(test.substring(0, result-1));

Output:

first;snd;3rd

You can ofc change the 3 in the loop with the number of arguments you need

Upvotes: 2

Akceptor
Akceptor

Reputation: 1932

Use StringUtils.ordinalIndexOf() from Apache

Finds the n-th index within a String, handling null. This method uses String.indexOf(String).

Parameters:

str - the String to check, may be null

searchStr - the String to find, may be null

ordinal - the n-th searchStr to find

Returns: the n-th index of the search String, -1 (INDEX_NOT_FOUND) if no match or null string input

Or this way, no libraries required:

public static int ordinalIndexOf(String str, String substr, int n) {
    int pos = str.indexOf(substr);
    while (--n > 0 && pos != -1)
        pos = str.indexOf(substr, pos + 1);
    return pos;
}

Upvotes: 3

Related Questions