6

Do you have any ideas how could I get first character after second dot of the string.

String str1 = "test.1231.asdasd.cccc.2.a.2";
String str2 = "aaa.1.22224.sadsada";

In first case I should get a and in second 2. I thought about dividing string with dot, and extracting first character of third element. But it seems to complicated and I think there is better way.

Deepesh kumar Gupta
  • 884
  • 2
  • 11
  • 29
Suule
  • 2,197
  • 4
  • 16
  • 42

7 Answers7

10

How about a regex for this?

Pattern p = Pattern.compile(".+?\\..+?\\.(\\w)");
Matcher m = p.matcher(str1);

if (m.find()) {
     System.out.println(m.group(1));
}

The regex says: find anything one or more times in a non-greedy fashion (.+?), that must be followed by a dot (\\.), than again anything one or more times in a non-greedy fashion (.+?) followed by a dot (\\.). After this was matched take the first word character in the first group ((\\w)).

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 1
    Can you please explain the regex? – Jack Flamp Aug 24 '18 at 11:14
  • 6
    The OP did not mandate the desired character to be a word character, so you should use just `.` instead of `\w`. And you may avoid repeating yourself: `Pattern p = Pattern.compile("(?:.+?\\.){2}(.)");`. If you want to extract a `char` without going through a `String`, you can also use `Matcher m = p.matcher(str1); if(m.find()) { char c = str1.charAt(m.start(1)); }`. Or, if you want a string, you can do it ad-hoc: `String s = str1.replaceFirst("(?:.+?\\.){2}(.).*", "$1");`. – Holger Aug 24 '18 at 12:32
  • `.+?` -> `.*?` there's nowhere said that characters are expected between dots – loa_in_ Aug 24 '18 at 15:05
  • @loa_in_ youre probably right, I just took the OPs examples as they were in the question – Eugene Aug 25 '18 at 08:06
2

Without using pattern, you can use subString and charAt method of String class to achieve this

// You can return String instead of char
public static char returnSecondChar(String strParam) {
    String tmpSubString = "";
   // First check if . exists in the string.
    if (strParam.indexOf('.') != -1) {
        // If yes, then extract substring starting from .+1  
        tmpSubString = strParam.substring(strParam.indexOf('.') + 1);
        System.out.println(tmpSubString);

       // Check if second '.' exists
        if (tmpSubString.indexOf('.') != -1) {

            // If it exists, get the char at index of . + 1  
            return tmpSubString.charAt(tmpSubString.indexOf('.') + 1);
        }
    }
    // If 2 '.' don't exists in the string, return '-'. Here you can return any thing
    return '-';
}
Ashishkumar Singh
  • 3,580
  • 1
  • 23
  • 41
2

Usually regex will do an excellent work here. Still if you are looking for something more customizable then consider the following implementation:

private static int positionOf(String source, String target, int match) {
    if (match < 1) {
        return -1;
    }
    int result = -1;

    do {
        result = source.indexOf(target, result + target.length());
    } while (--match > 0 && result > 0);

    return result;
}

and then the test is done with:

String str1 = "test..1231.asdasd.cccc..2.a.2.";

System.out.println(positionOf(str1, ".", 3)); -> // prints 10
System.out.println(positionOf(str1, "c", 4)); -> // prints 21
System.out.println(positionOf(str1, "c", 5)); -> // prints -1
System.out.println(positionOf(str1, "..", 2)); -> // prints 22 -> just have in mind that the first symbol after the match is at position 22 + target.length() and also there might be none element with such index in the char array.

dbl
  • 1,109
  • 9
  • 17
1

You could do it by splitting the String like this:

public static void main(String[] args) {
    String str1 = "test.1231.asdasd.cccc.2.a.2";
    String str2 = "aaa.1.22224.sadsada";

    System.out.println(getCharAfterSecondDot(str1));
    System.out.println(getCharAfterSecondDot(str2));
}

public static char getCharAfterSecondDot(String s) {
    String[] split = s.split("\\.");
    // TODO check if there are values in the array!
    return split[2].charAt(0);
}

I don't think it is too complicated, but using a directly matching regex is a very good (maybe better) solution anyway.

Please note that there might be the case of a String input with less than two dots, which would have to be handled (see TODO comment in the code).

deHaar
  • 17,687
  • 10
  • 38
  • 51
1

You can use Java Stream API since Java 8:

String string = "test.1231.asdasd.cccc.2.a.2";
Arrays.stream(string.split("\\."))                 // Split by dot
      .skip(2).limit(1)                            // Skip 2 initial parts and limit to one
      .map(i -> i.substring(0, 1))                 // Map to the first character
      .findFirst().ifPresent(System.out::println); // Get first and print if exists

However, I recommend you to stick with Regex, which is safer and a correct way to do so:


Here is the Regex you need (demo available at Regex101):

.*?\..*?\.(.).*

Don't forget to escape the special characters with double-slash \\.

String[] array = new String[3];
array[0] = "test.1231.asdasd.cccc.2.a.2";
array[1] = "aaa.1.22224.sadsada";
array[2] = "test";

Pattern p = Pattern.compile(".*?\\..*?\\.(.).*");
for (int i=0; i<array.length; i++) {
    Matcher m = p.matcher(array[i]);
    if (m.find()) {
         System.out.println(m.group(1));
    }
}

This code prints two results on each line: a, 2 and an empty lane because on the 3rd String, there is no match.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • Using `string.split("\\.", 3)` makes the `limit(1)` obsolete. Since the stream has at most one element, you can use `forEach(…)` instead of `.findFirst().ifPresent(…)`. In the regex, the `.*` at the end is obsolete. – Holger Aug 24 '18 at 12:31
0

A plain solution using String.indexOf:

public static Character getCharAfterSecondDot(String s) {
    int indexOfFirstDot = s.indexOf('.');
    if (!isValidIndex(indexOfFirstDot, s)) {
        return null;
    }

    int indexOfSecondDot = s.indexOf('.', indexOfFirstDot + 1);
    return isValidIndex(indexOfSecondDot, s) ?
            s.charAt(indexOfSecondDot + 1) :
            null;
}

protected static boolean isValidIndex(int index, String s) {
    return index != -1 && index < s.length() - 1;
}

Using indexOf(int ch) and indexOf(int ch, int fromIndex) needs only to examine all characters in worst case.

And a second version implementing the same logic using indexOf with Optional:

public static Character getCharAfterSecondDot(String s) {
    return Optional.of(s.indexOf('.'))
            .filter(i -> isValidIndex(i, s))
            .map(i -> s.indexOf('.', i + 1))
            .filter(i -> isValidIndex(i, s))
            .map(i -> s.charAt(i + 1))
            .orElse(null);
}
LuCio
  • 5,055
  • 2
  • 18
  • 34
-1

Just another approach, not a one-liner code but simple.

public class Test{
    public static void main (String[] args){
        for(String str:new String[]{"test.1231.asdasd.cccc.2.a.2","aaa.1.22224.sadsada"}){
            int n = 0;
            for(char c : str.toCharArray()){
                if(2 == n){
                    System.out.printf("found char: %c%n",c);
                    break;
                }
                if('.' == c){
                    n ++;   
                }
            }
        }
    }
}

found char: a
found char: 2