'Given string filter a part of it based on a pattern then add to array-list

Given a string with repeating pattern here:

 String s = NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500
  • Essentially I want way where when NameJJ and firstname are beside each other like at top it stores value beside them which is arraylist1 = [120,200].

  • Essentially I want way where all field with NameBB and secondname are beside each other to store the value beside them which is arraylist2 = [100,300].

  • Essentially I want way where all field with NameJJ and thirdname are beside each other to store the value beside them which is arraylist3 = [150,500].

I was trying to do this to say if string contains NameJJ and contains firstname should filter out value beside it but I'm confused on how I would do that, this is the code :

if (s.contains(NameJJ) && s.contains(firstname))
   Pattern reg = Pattern.compile(",");
ArrayList<String> SANR = reg.splitAsStream(s)    
        .filter(role -> role.contains(""))
        .map(String::trim)
        .collect(Collectors.toCollection(ArrayList::new));


Solution 1:[1]

Your String s holds the complete data so if (s.contains(NameJJ) && s.contains(firstname)) will always be true. You have to split the blocks first, then look at the values.

Your data block contains 3 data each so that's the number you have to divide by in loop condition and multiply with in array access

String s = "NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500";
String[] split = s.split(",");
List<Integer> first = new ArrayList<>();
List<Integer> second = new ArrayList<>();
List<Integer> third = new ArrayList<>();
for (int i = 0; i < split.length / 3; i++) {
    // first data block is Name..
    // second block is firstname/secondname/thirdname
    // third block hold the number you want
    if (split[3 * i].trim().equals("NameJJ") && split[3 * i + 1].trim().equals("ABC/firstname")) {
        first.add(Integer.parseInt(split[3 * i + 2].trim()));
    } else if (split[3 * i].trim().equals("NameBB") && split[3 * i + 1].trim().equals("ABC/secondname")) {
        second.add(Integer.parseInt(split[3 * i + 2].trim()));
    } else if (split[3 * i].trim().equals("NameCC") && split[3 * i + 1].trim().equals("ABC/thirdname")) {
        third.add(Integer.parseInt(split[3 * i + 2].trim()));
    }
}
System.out.println(first);
System.out.println(second);
System.out.println(third);

Output is

[120, 200]
[100, 300]
[150, 500]

Solution 2:[2]

As I've answered in a previous question of yours, whenever you're having a certain pattern repeating itself, you should use a regex to extract the sub-bits of your pattern.

Streams are not designed to keep track of a "first" or "last" element. They're mainly stateless operations, with a few exceptions for distinct, sorted and similar. Stateless operations start their execution even before the previous one has finished its computation. This is why they have no recollection of a first or last result and also why we cannot use them for this kind of tasks.

What you could do is to employ 3 regex to match your pattern for nameJJ, nameBB and nameCC, and use capturing groups to identity and extract every desired sub-bit.

The following 3 regex can be used to match your patterns:

(\w+)JJ,(\w+)\/(\w+),(\d+)
(\w+)BB,(\w+)\/(\w+),(\d+)
(\w+)CC,(\w+)\/(\w+),(\d+)

Here is a snippet of the code implementation:

public class Main {
    public static void main(String[] args) {
        String s = "NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500";

        List<Integer> listNameJJ = getList("(\\w+)JJ,(\\w+)\\/(\\w+),(\\d+)", s);
        List<Integer> listNameBB = getList("(\\w+)BB,(\\w+)\\/(\\w+),(\\d+)", s);
        List<Integer> listNameCC = getList("(\\w+)CC,(\\w+)\\/(\\w+),(\\d+)", s);

        System.out.println(listNameJJ);
        System.out.println(listNameBB);
        System.out.println(listNameCC);
    }

    public static List<Integer> getList(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        List<Integer> list = new ArrayList<>();

        while (matcher.find()) {
            list.add(Integer.valueOf(matcher.group(4)));
        }

        return list;
    }
}

Here is also a link to test the code above:

https://ideone.com/TES5UY

Solution 3:[3]

Here is another example,

public class Application {

    public static void main(String[] args) {

        String yourString = "NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500";
        String myString = "NameKK,ZXY/kname,510, NameQQ,HLM/kname,210, NameKK,ZXY/kname,210,";

        // Test 1
        System.out.println(getValues("NameJJ", "firstname", yourString));
        // Test 2
        System.out.println(getValues("NameKK", "kname", myString));
    }

    private static List<Integer> getValues(String str1, String str2, String inputString) {

        // Note* List is an ordered sequence of elements.

        List<Integer> value = new ArrayList<Integer>();
        // Extract Values
        Matcher m = Pattern.compile("-?\\d+(,\\d+)*?\\.?\\d+?")
                .matcher(inputString);
        while (m.find()) {
            value.add(Integer.parseInt(m.group().trim()));
        }

        // Extract Keys
        List<String> key = List.of(inputString.split("\\d+"));

        List<Integer> result = new ArrayList<Integer>();
        // Filtering
        for (int i = 0; i < value.size(); i++) {
            
            if (key.get(i).trim().contains(str1) 
                    && key.get(i).trim().contains(str2)) {

                result.add(value.get(i));
            }

        }
        return result;
    }
}

Console O/P:

 [120, 200]
 [510, 210]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stefan Warminski
Solution 2 Dan
Solution 3