c++stl

C++ How to convert a for loop to std::count_if


Here's a code that, for each element, counts the number of elements that are not connected to it.

bool conn[100][100];
for(int i=0; i<N; i++){
  int cnt=0;
  for(int j=0; j<N; j++) cnt+=!(conn[i][j]||conn[j][i]);
  std::cout<<cnt<<"\n";
}

I want to convert it into std::count_if statement.

for(int i=0; i<N; i++){
    std::cout<<count_if(conn[i], conn[i]+N, [&](){auto k; return !(conn[i][k]||conn[k][i]);})<<"\n";
}

How can I do this? Seems like I should access to index of iterator in lambda function.


Solution

  • If you really want to use std::count_if and have access to C++20 ranges, you can run it on cartesian product of indices:

    template <size_t N>
    size_t count_disconnected(const bool (&matrix)[N][N]) {
        const auto range = std::views::iota<size_t>(0, N);
        const auto product = std::views::cartesian_product(range, range);
        return std::ranges::count_if(product, [&matrix](const auto& pair) {
            const auto [i, j] = pair;
            return !matrix[i][j] && !matrix[j][i];
        });
    }
    

    Please note that since your predicate is symmetric, both your algorithm and this one will double count everything except the diagonal. You can fix this by changing the second loop condition to j < i (or <= if still want to check the diagonal), or adding j < i && to the predicate.