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.
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.
Share Improve this question edited Feb 15 at 16:45 Tim Diekmann 8,47611 gold badges48 silver badges72 bronze badges asked Feb 15 at 5:12 navyismnavyism 233 bronze badges 11 | Show 6 more comments2 Answers
Reset to default 2If 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.
2d arrays in C and C++ are successions of 1 d arrays in memory. Use this to calculate in a single for_each connection to element neq (prefering for_each that does not return value to count if). A single line of the matrix has to be observed
bool conn [3] [3] = {
{false, true, false},
{true, false, true},
{false, false, false}
};
const int N (3);
#include <iostream>
#include <algorithm>
int main (int argc, char* argv []) {
auto nel ((int) 1), //element number
nct (0);
auto conn1d ((bool*) &conn);
std::for_each ((const bool*) &conn1d [nel * N], (const bool *) &conn1d [(nel+1)*N], [&nct] (const auto& b) {
nct += b?1:0;
});
std::cout << "\tnb of element connected to element " << nel << " is " << nct << std::endl;
std::cout << "\tnb of element unconnected to element " << nel << " is " << N-nct << std::endl;
return 0;
}
std::valarray
. – Passer By Commented Feb 15 at 5:19std::count_if
into service with some complicated lambda, but it'd only obscure the logic. – Igor Tandetnik Commented Feb 15 at 5:29conn
is, so that we get a clearer picture. – PaulMcKenzie Commented Feb 15 at 5:31std::count_if()
is not really suitable for your task without a significant amount of fiddling. The overload ofstd::count_if
that accepts a function object ONLY passes the value of an element (obtained by dereferencing an iterator) to the function. It doesn't pass the iterator itself, nor does it pass indices. Your code requires being able to access indices. Sticking with your loops is among the simplest (and more maintainable) options. – Peter Commented Feb 15 at 13:11