2016-02-23 9 views
8

std::setの要素に基づいてstd::vectorをスライスする良い方法はありますか?言い換えれば、std::setの要素は、ベクトルに必要なインデックスを保持しています。確かに、私はコードでこれを達成することができます:`std :: set`の要素に基づいて` std :: vector`をスライスする方法

正しく

1.2 
4.5 
5.6 

を返し

#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")); 
} 

をしかし、これは少し不器用な感じ。より良い方法がありますか?

答えて

6

あなたは単に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

あなたはまたstd::transformstd::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

を使用することができ、 'のstd ::ベクトル:: 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; 
} 
関連する問題