2015-11-03 1 views
3

У меня есть два вектора a и b с одинаковым размером.Удалить векторный элемент использовать условие в векторе <bool>

vector<int> a{ 4, 3, 1, 3, 1}; 
vector<bool> b{false,false,true,false,true}; 

Я хочу, чтобы удалить элемент в a, если тот же элемент в b (тот же индекс) истинно.

После применения функции: а = 4,3,3

Примечание: Я хочу использовать std алгоритмы и функции, а не просто для цикла.

+0

Что вы имеете в виду, используя 'std' вместо' for' loop? – Melebius

+2

Использование std-алгоритмов, таких как remove, transform и т. Д. Вместо необработанного цикла. – melak47

+0

@ melak47, точно! – user1436187

ответ

6
std::vector<int> v {1,2,3,4,5,6}; 
    std::vector<bool> b {true, false, true, false, true, false}; 

    v.erase(std::remove_if(v.begin(), v.end(), 
     [&b, &v](int const &i) { return b.at(&i - v.data()); }), v.end()); 

LIVE DEMO

+1

Вопрос помечен C++ 11, поэтому нет общих ягнят. И используйте более безопасную перегрузку стирания, это будет сбой, если все элементы будут «ложными». –

+0

@GregorMcGregor справедливо исправлено. – 101010

+0

Никогда не отлаживайте при вставании http://coliru.stacked-crooked.com/a/2083debebfeb4718 –

4
void filter(std::vector<int>& v, const std::vector<bool>& b) 
{ 
    assert(v.size() == b.size()); 
    auto it = b.begin(); 
    v.erase(std::remove_if(v.begin(), v.end(), [&](int) { return *it++; }), v.end()); 
} 

Demo

+2

Это зависит от 'remove_if', применяя предикат к элементам по порядку, что не гарантируется. –

1

Я попытался раздвинуть пределы, не используя лямбды, только std функции. У меня есть два решения, но все они требуют внешней памяти:

Первое решение

#include <algorithm> 
#include <iostream> 
#include <iterator> 
#include <tuple> 
#include <utility> 
#include <vector> 

using namespace std; 

int main(int argc, char* argv[]) { 
    vector<int> a{4, 3, 1, 3, 1}; 
    vector<bool> b{true, false, true, false, true}; 
    vector<int> c; 
    vector<pair<int,bool>> tmp; 

    // Join                  
    transform(begin(a), end(a), 
      begin(b), 
      back_inserter(tmp), 
      make_pair<int const&,bool const&>); 

    // Filter                  
    auto last = partition(begin(tmp), end(tmp), 
         (bool const&(*)(std::pair<int,bool> const&)) 
         std::get<1,int,bool>); 

    // Copy back                 
    transform(begin(tmp), last, 
      back_inserter(c), 
      (int const&(*)(pair<int,bool> const&)) 
      get<0,int,bool>); 

    // Print (you could do a.swap(c) if you just want to modify 'a' 
    copy(begin(c), end(c), ostream_iterator<int>(cout, ", ")); 
    cout << endl; 
} 

Второе решение

Он использует valarray вместо:

// 2nd solution using valarray             
    valarray<int> va(&a[0], a.size()); 
    valarray<bool> vb(b.size()); 
    copy(begin(b), end(b), begin(vb)); 

    valarray<int> vc(va[vb]); 
    copy(begin(vc), end(vc), ostream_iterator<int>(cout, ", ")); 
    cout << endl; 
0

Без алгоритма STL , но с модифицированной версией std::remove_if:

template<class ForwardIt1, class ForwardIt2, class UnaryPredicate> 
ForwardIt1 remove_if_tagged(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, 
          UnaryPredicate p) 
{ 
    ForwardIt1 result = first1; 
    for (; first1 != last1; ++first1, ++first2) { 
     if (!p(*first1, *first2)) { 
      *result++ = *first1; 
     } 
    } 
    return result; 
} 

std::vector<int> a{ 4, 3, 1, 3, 1}; 
std::vector<bool> b{false,false,true,false,true}; 
a.erase(
    remove_if_tagged(
    a.begin(), a.end(), 
    b.begin(), 
    [](int, bool tag) { return tag; } 
), 
    a.end() 
); 
Смежные вопросы