'How do I access index from filter in java?

I'm planning to convert the following without a for loop and using functional programming:

int count = 0;
for (int i = 0; i < 5; i++) { //Feedback: avoid for and mutation
  if (target.charAt(i) == letter && target.charAt(i) == guess.charAt(i)) {
    count++;
  }
}

How do I achieve the if condition with the indexes with the filter?



Solution 1:[1]

You can consider using IntStream.range() for this case

int count = (int) IntStream.range(0, 5)
        .filter(i -> target.charAt(i) == letter && target.charAt(i) == answer.charAt(i))
        .count();

Solution 2:[2]

This seems like a Wordle related problem, based on the words both having five letters. If you are open to using a third-party library, the following code will work using Eclipse Collections.

@Test
public void zipChar()
{
    char letter = 'o';
    CharAdapter target = Strings.asChars("tools");
    CharAdapter guess = Strings.asChars("boots");

    int count = target.zipChar(guess)
        .count(pair -> pair.getOne() == pair.getTwo() && pair.getOne() == letter);

    Assertions.assertEquals(2, count);
}

The code zips two Strings together and uses the count method which takes a Predicate. Since the Strings are zipped together into CharCharPair instances, there is no need to use indexes or filter here.

There is a Java 17 Wordle Checker tutorial from José Paumard on the Java YouTube channel that you might find helpful.

Note: I am a committer for Eclipse Collections

Solution 3:[3]

It seems like you are want to find out how many given characters (denoted as letter in your code) there are in two strings target and guess at the same positions in both.

Firstly you shouldn't hard-code i < 5 conditions like that. I doubt that you intended to create a method that is able to process only strings with a length of precisely 5 characters. Strings of length 3 or 8 would require another method? Also target and guess could be of different lengths.

Keeping all that in mind this condition from your loop boils down to:

    `i < Math.min(target.length(), guess.length())`.

To implement this task using Stream IPA you might mimic your for loop with a help of IntStream.

Its method range(), which actually utilizes for loop under the hood, except two arguments: starting index and end index (exclusive). So arguments passed to the range() are basically the same as you might use in a for loop.

filter() expects an instance of Predicate which is a functional interface build-in in JDK, and represents boolean condition.

Method count() is a terminal operation that returns a number of elements in the stream (after applying all preceding operations that reduce the number of elements) as a long.

The code might look like this:

    long count = IntStream.range(0, Math.min(target.length(), guess.length()))
                .filter(i -> target.charAt(i) == letter && 
                             target.charAt(i) == guess.charAt(i))
                .count();

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
Solution 2
Solution 3