Franneck
Franneck

Reputation: 31

Copy index of vector Elements with condition

I want to save the indices of my bool vector where the vector element is false.

I have the following code:

vector<bool> incumbent_solution; // (0,0,0,1,1,0,0)...
vector<int> I_minus_S(incumbent_solution.size());

auto it = copy_if(incumbent_solution.begin(), incumbent_solution.end(),
        I_minus_S.begin(), [&incumbent_solution](auto i) {if (incumbent_solution[i] == 0] return i; });
I_minus_S.erase(it, I_minus_S.end());

But it only stores True in my Vector and not the indices. What is my lambda doing wrong?

Upvotes: 0

Views: 2242

Answers (2)

Shakiba Moshiri
Shakiba Moshiri

Reputation: 23784

std::vector< bool >  vb = { 0,0,0,1,1,0,0 };
std::vector< int >   vi;

unsigned counter = 0;
for( bool b : vb ){
    if( !b ){
        vi.push_back( counter );
    }
    ++counter;
}

for( int& i : vi ){
    std::cout << i << '\n';
}  

std::copy_if accepts an UnaryFunction that should return true or false. It is better to use a simple for.


If you are demanding to use algorithm library, you can use transform

std::vector< bool >  vb = { 0,0,0,1,1,0,0 };
std::vector< int >   vi;

int counter = -1;

std::transform( vb.begin(), vb.end(), std::back_inserter( vi ),
                [&](const bool b ){
                    counter++;
                    if( !b ) return counter;
                }
               );  

but the problem with that is, for true condition returns 0 to the index of vi. Although you can use -1 and later remove them inside vi

                [&](const bool b ){
                    counter++;
                    if( !b ) return counter;
                    else     return -1;
                }

but still a simple for is a better solution.

Upvotes: 1

Akira
Akira

Reputation: 4473

The std::copy_if works differently than you expected, it passes the actual element to the predicate and copies it into the second container if the predicate returns true.

If you want indexes, use a simple for loop:

std::vector<bool> incumbent_solution { 0, 0, 0, 1, 1, 0, 0, 1, 1 };
std::vector<int> I_minus_S(incumbent_solution.size());

std::size_t last = 0;

for(std::size_t index = 0; index < incumbent_solution.size(); ++index) {
    if(incumbent_solution[index] == false)
        I_minus_S[last++] = index;
}

I_minus_S.erase(I_minus_S.begin() + last, I_minus_S.end());

Upvotes: 0

Related Questions