rokk crow
rokk crow

Reputation: 47

Java, how to split given string into three seperate parts?

I have a list of these strings which are formatted like the following:

9-11 w: wwtxmsjwjwlw separate to: 9-11 , w , wwtxmsjwjwlw

5-6 g: wggghg separate to 5-6 , g , wggghg

1-5 g: dxggdggb seperate to 1-5 , g , dxggdggb

5-13 f: lfgdplfffxffswck separate to 5-13 , f, lfgdplfffxffswck

6-7 z: zzzzgzzzz separate to 6-7 , z , zzzzgzzzz

these are just examples, so there are more in reality, just to help let you know what it looks like, left side is given and right side is what I want to change it too and be able to access the values for future uses like storing in three arrays each type of the three values this way they share the same index... how can i separate each part and keep the values in a way so that I can access them? here is what I tried:

int[] a1 = new int[10];
int[] a2 = new int[10];
int[] a3 = new int[10];
for(int i=0;i<a1.length;i++){
    a1[i].split("^[0-9]-[0-9]");//take the format of whatever looks like "int-int"
    a1[i].split("/d[a/z]:");//take the letter before the: - :"char:"
    a1[i].split("[a-z]{1,}");// take the long text that has a minimum of 1 char "String"for example -zzzzgzzzz

}

help would be interested, let me know please if there are more efficient ways than my idea with the arrays and bad performance with regexes and fix mine since it doesn't work. The aim of the question is To take the letter/char occurrence, basically checking if the occurrence from the given range int-int is true in the string of it is true then count++, it's not necessarily true- nothing happens. -but I want to check if the letter appears in the given range to the string if this makes sense Help improving the question would also be helpful thanks

here is again code using the solution below so thanks to @wp78de, I tried to change it so that it uses reader.nextLine() to get inputs and places in an array-

    public static Scanner reader= new Scanner(System.in);
     public static int testString(String s, int c) {
            String regex = "(\\d+)-(\\d+) (\\w): ([a-z]+)";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(s);
            
            matcher.find();
            //System.out.println("Full match: " + matcher.group(0));
            
            Pattern p = Pattern.compile(matcher.group(3));
            Matcher m = p.matcher(matcher.group(4));
            long count = m.results().count();
            if(count < Long.parseLong(matcher.group(1)) || count > Long.parseLong(matcher.group(2))) {
            } 
            else {
                c++;
            }
            return c;
        }
        
        public static void main (String[] args) throws java.lang.Exception
        {
            int count=0;
            for(int i=0;i<1000;i++) {
                String ss = reader.nextLine();
                for (String s: ss.split("\n")) {
                    System.out.println(s);
                    testString(s,count);
                    System.out.println(s + "    :   "+ count);
                }
            }
            
            System.out.println(count);

        }
}

Upvotes: 1

Views: 323

Answers (2)

wp78de
wp78de

Reputation: 18950

I think you are approaching this in the wrong way; just feed the entire text or line by line to a regex that matches all three parts at once, e.g.

(\d+-\d+) (\w): ([a-z]+)

I've extracted this into a function that expects single lines, matches the individual parts, and tests the specified occurrence range.

Regex Demo; Sample Code:

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

class Ideone
{
    public static boolean testString(String s) {
        String regex = "(\\d+)-(\\d+) (\\w): ([a-z]+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(s);
        
        matcher.find();
        //System.out.println("Full match: " + matcher.group(0));
        
        Pattern p = Pattern.compile(matcher.group(3));
        Matcher m = p.matcher(matcher.group(4));
        long count = m.results().count();
        if(count < Long.parseLong(matcher.group(1)) || count > Long.parseLong(matcher.group(2))) {
            return false;
        } else {
            return true;
        }
    }
    
    public static void main (String[] args) throws java.lang.Exception
    {
        final String string = "9-11 w: wwtxmsjwjwlw\n"
             + "5-6 g: wggghg\n"
             + "1-5 g: dxggdggb\n"
             + "5-13 f: lfgdplfffxffswck\n"
             + "6-7 z: zzzzgzzzz";
        
        for (String s: string.split("\n")) {
            System.out.println(s);
            System.out.println(testString(s));
        }
    }
}

It might be worth to add anchors to for the ^ start and $ end position: ^(\d+-\d+) (\w): ([a-z]+)$

Upvotes: 1

Oleg Cherednik
Oleg Cherednik

Reputation: 18245

You can use RegExp and convert each input line into separate class object to process these data further.

public final class Data {

    private final String one;
    private final String two;
    private final String three;

    public Data(String one, String two, String three) {
        this.one = one;
        this.two = two;
        this.three = three;
    }
}

private static final String REGEXP = "(?<one>\\d+-\\d+)\\s*(?<two>\\w+)\\s*:\\s*(?<three>\\w+)";

public static List<Data> convertData(List<String> lines) {
    Pattern pattern = Pattern.compile(REGEXP);

    return lines.stream()
                .map(pattern::matcher)
                .filter(Matcher::matches)
                .map(matcher -> new Data(matcher.group("one"), matcher.group("two"), matcher.group("three")))
                .collect(Collectors.toList());
}

Demo:

List<String> lines = Arrays.asList(
        "9-11 w: wwtxmsjwjwlw",
        "5-6 g: wggghg",
        "1-5 g: dxggdggb",
        "5-13 f: lfgdplfffxffswck",
        "6-7 z: zzzzgzzzz ");
List<Data> data = convertData(lines);

Upvotes: 0

Related Questions