2016-02-23 2 views
8

Gibt es eine gute Möglichkeit, eine std::vector basierend auf Elementen in einer std::set zu schneiden? Mit anderen Worten, die Elemente in std::set enthalten die Indizes, die ich im Vektor haben möchte. Sicher, ich dies mit dem Code ausführen kann:Wie schneidet man einen `std :: vector` auf Basis von Elementen in` std :: set`

#include <set> 
#include <vector> 
#include <iostream> 
#include <iterator> 

template <typename T> 
std::vector <T> slice(
    std::vector <T> const & x, 
    std::set <unsigned int> const & I 
) { 
    auto y = std::vector <T>(); 
    for(auto const & i : I) 
     y.push_back(x[i]); 
    return y; 
} 

int main() { 
    auto x = std::vector <double> { 1.2, 2.3, 3.4, 4.5, 5.6}; 
    auto I = std::set <unsigned int> { 0, 3, 4}; 
    auto y = slice(x,I); 
    std::copy(y.begin(),y.end(),std::ostream_iterator <double>(
     std::cout,"\n")); 
} 

, die korrekt zurückgibt

1.2 
4.5 
5.6 

Allerdings fühlt sich das ein wenig unbeholfen. Gibt es einen besseren Weg?

Antwort

6

Sie können dies erreichen, indem einfach std::transform mit:

int main() 
{ 
    std::vector<double> x { 1.2, 2.3, 3.4, 4.5, 5.6}; 
    std::set<unsigned int> I { 0, 3, 4}; 
    std::vector<double> y(I.size()); 

    std::transform(I.begin(), I.end(), y.begin(), 
    [&x](unsigned int i) { return x[i]; }); 

    std::copy(y.begin(),y.end(),std::ostream_iterator <double>(std::cout,"\n")); 
} 
4

Sie auch std::transform und std::back_inserter

template <typename T> 
std::vector <T> slice(
    std::vector<T> const &x, 
    std::set<unsigned int> const &I) 
{ 
    std::vector<double> result; 
    std::transform(I.begin(), I.end(), std::back_inserter(result), 
     [&x](unsigned int i) { return x[i]; }); 
    return result; 
} 
+1

Vergessen Sie nicht 'std :: vector :: reserve' nutzen könnten. – LogicStuff

2
template <typename T> 
std::vector <T> slice2(
    std::vector <T> const & x, 
    std::set <unsigned int> const & I 
    ) 
{ 
    auto z = std::vector <double>(); 
    std::for_each(I.begin(), I.end(), [&](const unsigned int &i) 
    { 
     z.push_back(x[i]); 
    }); 
    return z; 
}