HuserB1989
HuserB1989

Reputation: 380

How can I scope three different conditions using the same loop in Java?

I would like to count countX and countX using the same loop instead of creating three different loops. Is there any easy way approaching that?

public class Absence {
    private static File file = new File("/Users/naplo.txt");
    private static File file_out = new File("/Users/naplo_out.txt");
    private static BufferedReader br = null;
    private static BufferedWriter bw = null;

    public static void main(String[] args) throws IOException {
        int countSign = 0;
        int countX = 0;
        int countI = 0;
        String sign = "#";
        String absenceX = "X";
        String absenceI = "I";

        try {
            br = new BufferedReader(new FileReader(file));
            bw = new BufferedWriter(new FileWriter(file_out));

            String st;
            while ((st = br.readLine()) != null) {
                for (String element : st.split(" ")) {

                    if (element.matches(sign)) {
                        countSign++;
                        continue;
                    }
                    if (element.matches(absenceX)) {
                        countX++;
                        continue;
                    }
                    if (element.matches(absenceI)) {
                        countI++;
                    }
                }
            }
            System.out.println("2. exerc.: There are " + countSign + " rows int the file with that sign.");
            System.out.println("3. exerc.: There are " + countX + " with sick note, and " + countI + " without sick note!");
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Absence.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

text file example:

# 03 26
Jujuba Ibolya IXXXXXX
Maracuja Kolos XXXXXXX

Upvotes: 0

Views: 57

Answers (3)

George Z.
George Z.

Reputation: 6808

Both answers check if the word (element) matches all regular expressions while this can (and should, if you ask me) be avoided since a word can match only one regex. I am referring to the continue part your original code has, which is good since you do not have to do any further checks.

So, I am leaving here one way to do it with Java 8 Streams in "one liner".

But let's assume the following regular expressions:

String absenceX = "X*";
String absenceI = "I.*";

and one more (for the sake of the example):

String onlyNumbers = "[0-9]*";

In order to have some matches on them.

The text is as you gave it.

public class Test {
    public static void main(String[] args) throws IOException {
        File desktop = new File(System.getProperty("user.home"), "Desktop");
        File txtFile = new File(desktop, "test.txt");

        String sign = "#";
        String absenceX = "X*";
        String absenceI = "I.*";
        String onlyNumbers = "[0-9]*";
        List<String> regexes = Arrays.asList(sign, absenceX, absenceI, onlyNumbers);

        List<String> lines = Files.readAllLines(txtFile.toPath());

        //@formatter:off
        Map<String, Long> result = lines.stream()
                .flatMap(line-> Stream.of(line.split(" "))) //map these lines to words
                .map(word -> regexes.stream().filter(word::matches).findFirst()) //find the first regex this word matches
                .filter(Optional::isPresent) //If it matches no regex, it will be ignored
                .collect(Collectors.groupingBy(Optional::get, Collectors.counting())); //collect
        System.out.println(result);
    }

}

The result:

{X*=1, #=1, I.=2, [0-9]=2}

X*=1 came from word: XXXXXXX

#=1 came from word: #

I.*=2 came from words: IXXXXXX and Ibolya

[0-9]*=2 came from words: 03 and 06

Ignore the fact I load all lines in memory.

Upvotes: 1

Mahmood Darwish
Mahmood Darwish

Reputation: 546

I think you meant using less than 3 if statements. You can actually so it with no ifs.

In your for loop write this:

Countsign += (element.matches(sign)) ? 1 : 0;
CountX += (element.matches(absenceX)) ? 1 : 0;
CountI += (element.matches(absenceI)) ? 1 : 0;

Upvotes: 1

HuserB1989
HuserB1989

Reputation: 380

So I made it with the following lines to work. It escaped my attention that every character need to be separated from each other. Your ternary operation suggestion also nice so I will use it.

String myString;
        while ((myString = br.readLine()) != null) {
            String newString = myString.replaceAll("", " ").trim();
            for (String element : newString.split(" ")) {

                countSign += (element.matches(sign)) ? 1 : 0;
                countX += (element.matches(absenceX)) ? 1 : 0;
                countI += (element.matches(absenceI)) ? 1 : 0;

Upvotes: 0

Related Questions