2016-02-23 46 views
8

Czy istnieje dobry sposób na cięcie std::vector na podstawie elementów w std::set? Innymi słowy, elementy w std::set posiadają indeksy, które chcę w wektorze. Oczywiście, można to osiągnąć za pomocą kodu:Jak wycinać `std :: vector` na podstawie elementów w` 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")); 
} 

które poprawnie zwraca

1.2 
4.5 
5.6 

to jednak czuje się trochę niezdarny. Czy istnieje lepszy sposób?

Odpowiedz

6

Można to osiągnąć po prostu za pomocą std::transform:

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

Można również użyć std::transform i 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

Nie zapomnij 'std :: vector :: reserve'. – 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; 
}