少し初心者の質問でごめんなさい。ベクトルとペアのベクトルがあります
typedef std::vector <int> TItems;
typedef std::vector < std::pair <int, int> > TPairs;
ペアのすべての最初のアイテムを1つのステップで別のベクトルに変換する方法はありますか
int main ()
{
TItems items;
TPairs pairs;
pairs.Push_back (std::make_pair(1,3));
pairs.Push_back (std::make_pair(5,7));
std::transform( items.begin(), items.end(), items.begin(), comp ( &pairs ) );
return 0;
}
ファンクターを設計する方法は?
class comp
{
private:
TPairs *pairs;
public:
comp ( TPairs *pairs_ ) : pairs ( pairs_) { }
unsigned int operator () ( const unsigned int index ) const
{
return (*pairs)[index].second != pairs->end(); //Bad idea
}
};
ラムダ式とループのない、もっとユーザーフレンドリーなメソッドがあるかもしれません。ご協力いただきありがとうございます。
std::get
はすでにライブラリ関数として提供されているので、ファンクターとして使ってほしいです!!
この行を書けたらいいのではないでしょうか!?
std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);
...しかし、それよりも少しひどいです。どのget
を使用するかを明確にする必要があります。
int main() {
std::vector<int> items;
std::vector<std::pair<int, int>> pairs;
pairs.Push_back(std::make_pair(1, 3));
pairs.Push_back(std::make_pair(5, 7));
std::transform(pairs.begin(), pairs.end(), std::back_inserter(items),
(const int& (*)(const std::pair<int, int>&))std::get<0>);
return 0;
}
問題は、std::get
オーバーロードされている 1。pair&
、2。const pair&
、および3. pair&&
をパラメーターとして使用するため、入力としてあらゆる種類のペアで機能します。残念ながら、オーバーロードはstd::transform
のテンプレート型の推定の邪魔になるため、元の行
std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);
収量
error: no matching function for call to ‘transform(std::vector<std::pair<int, int> >::iterator, std::vector<std::pair<int, int> >::iterator, std::back_insert_iterator<std::vector<int> >, <unresolved overloaded function type>)’
std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);
^
...
/usr/include/c++/4.8/bits/stl_algo.h:4915:5: note: template argument deduction/substitution failed:
note: couldn't deduce template parameter ‘_UnaryOperation’
std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);
std::get
のテンプレートを推測するときに、どのstd::transform
のオーバーロードを要求しているかがわからないため、手動で指定する必要があります。関数ポインタを正しい型にキャストすると、コンパイラは「get
がconst&
を取りconst&
を返すオーバーロードを使用してください!」と伝えます。
しかし、少なくとも私たちは標準ライブラリコンポーネントを使用しています(イェーイ)?
そして、行数に関しては、他のオプションよりも悪くはありません: http://ideone.com/6dfzxz
まず、 back_inserter
を transform
の3番目の引数として使用して、変換された値がの後ろにプッシュされるようにする必要があります。ベクター。
次に、intのペアを取り、最初のintを返すある種のファンクターが必要です。これは行う必要があります:
int firstElement( const std::pair<int, int> &p ) {
return p.first;
}
さて、ピースをまとめるには:
TPairs pairs;
pairs.Push_back( std::make_pair( 1, 3 ) );
pairs.Push_back( std::make_pair( 5, 7 ) );
TItems items;
std::transform( pairs.begin(), pairs.end(), std::back_inserter( items ),
firstElement );
このコードの後、items
には1と5が含まれます。
c ++ 03に関するfrerichまたはkotlinskiの回答を参照してください。
ラムダを使用したC++ 11ソリューション:
std::transform(pairs.begin(),
pairs.end(),
std::back_inserter(items),
[](const std::pair<int, int>& p) { return p.first; });
これはどう?
items.reserve(pairs.size());
for (size_t it = 0; it < pairs.size(); ++it) {
items.Push_back(pairs[it].first);
}
理解とデバッグが簡単です。
std::bind
を使ってみませんか?
std::transform(pairs.begin(),
pairs.end(),
std::back_inserter(items),
std::bind(&TPairs::value_type::first, std::placeholders::_1));
(C++ 11以外のコードの場合は、std::bind
をboost::bind
に置き換えます)
c ++ 11からの別の可能性は std::mem_fn
であり、これはstd::bind
を使用したソリューションに似ています。
std::transform(pairs.begin(),
pairs.end(),
std::back_inserter(items),
std::mem_fn(&std::pair<int,int>::first)
);