ufuk Yavuz
ufuk Yavuz

Reputation: 31

How to use findAny() to find a spesific value in a 2D Array

I have a 2D array as follows

int[][] seatsPrices = {{10,10,10,10,10,10,10,10,10,10},
                        {10,10,10,10,10,10,10,10,10,10},
                        {10,10,10,10,10,10,10,10,10,10},
                        {10,10,20,20,20,20,20,20,10,10},
                        {10,10,20,20,20,20,20,20,10,10},
                        {10,10,20,20,20,20,20,20,10,10},
                        {20,20,30,30,40,40,30,30,20,20},
                        {20,30,30,40,50,50,40,30,30,20},
                        {30,40,50,50,50,50,50,50,40,30}};

I'm asking the user to give a number. Let's say he gives 20. So, I want to code to compare that value with the seatsPrices array iteratively and find any i,j indexes of the seatsPrices array which its values is 20, and print it. I should probably use findAny() but I cannot figure out how to use it. Note: I need to find only one "20" and stop. Thus, using two nested loop, it causes some problems for me.

Upvotes: 0

Views: 143

Answers (3)

Alexander Petrovskiy
Alexander Petrovskiy

Reputation: 309

If you want to provide the user with a really any value, I'd suggest you getting all the appropriate items and get a random one thereafter. You can collect all the items matching with such a one-liner:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SpecificValueIn2DArray {
    static int[][] seatsPrices = {{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
    {10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
    {10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
    {10, 10, 20, 20, 20, 20, 20, 20, 10, 10},
    {10, 10, 20, 20, 20, 20, 20, 20, 10, 10},
    {10, 10, 20, 20, 20, 20, 20, 20, 10, 10},
    {20, 20, 30, 30, 40, 40, 30, 30, 20, 20},
    {20, 30, 30, 40, 50, 50, 40, 30, 30, 20},
    {30, 40, 50, 50, 50, 50, 50, 50, 40, 30}};

public List<int[]> getItemIndexCollection(int itemValue) {
    return IntStream.range(0, seatsPrices.length)
        .boxed()
        .flatMap(i ->
            IntStream.range(0, seatsPrices[i].length)
                .boxed()
                .map(j -> seatsPrices[i][j] == itemValue ? new int[]{i, j} : new int[]{-1, -1})
        )
        .filter(item -> item[0] != -1 && item[1] != -1)
        .collect(Collectors.toList());
}

}

and get a random element from the result list:

    final var actualResult = new SpecificValueIn2DArray().getItemIndexCollection(itemValue);
    final var random = new Random();
    final var pair = actualResult.get(random.nextInt(actualResult.size()));
    System.out.println(pair[0] + " " + pair[1]);
    System.out.println(SpecificValueIn2DArray.seatsPrices[pair[0]][pair[1]]);

Upvotes: 1

The .findAny() and .findFirst() stream methods are not the best for you. They both work by finding values and not indexes. The best here is to indeed iterate through your array until you find the value you want and stopping the iteration when the value is found. You could do as Alex said.

If you know your array is ordered (like it seems to be) you could do a binary search on it instead. Start by looking at the middle of the array, then check if the value there is your value, or if it is greater than it, or less than it.

  • If the value (middle of the array) is your value (20), the search ended.
  • If the value is greater than your value, the value (if present) is on the left side of your split in the middle.
  • If the value is smaller than your value, then the value you want is on the right side of your split.

You just have to repeat this algorithm on the side of the array your value is, until you find it.

Example 1D algorithm:

int binarySearch(int arr[], int lIndex, int rIndex, int searchValue)
{
    if (rIndex >= lIndex) {
        int pivot = lIndex + (rIndex - lIndex) / 2;
        if (arr[pivot] == searchValue)
            return pivot;
        if (arr[pivot] > searchValue)
            return binarySearch(arr, lIndex, pivot - 1, searchValue);
        return binarySearch(arr, pivot + 1, rIndex, searchValue);
    }
    return -1;
}

You can unwrap your 2D array into a 1D array and get the index, than just remap the index to a 2D index:

x = index / size;
y = index % size;

Upvotes: 1

Alex
Alex

Reputation: 126

I don't know why you would use findAny(), it seems much simpler to just iterate over the arrays and search for 20 and print out the i,j whenever you come across one.

for (int i = 0; i < seatPrices.length; i++) {
    for (int j = 0; j < seatPrices[0].length; j++) {
        if (seatPrices[i][j] == 20) 
            System.out.println(i + " " + j);
    }
}

If you know anything about the arrays (like they're sorted) you can come up with a quicker algorithm to find the indices.

If you want to find only one:

boolean found = false;
for (int i = 0; i < seatPrices.length && !found; i++) {
    for (int j = 0; j < seatPrices[0].length && !found; j++) {
        if (seatPrices[i][j] == 20) {
            System.out.println(i + " " + j);
            found = true;
        }
    }
}

Upvotes: 1

Related Questions