3

私は2つのベクトルを持っています

std::vector<int>   markedToBeRead(7);   // contains: 1,1,0,0,1,0,1
std::vector<float> myVec(7);            // contains: 1,2,3,4,5,6,7

markedToBeReadの対応するインデックスが値を持つmyVec からこれらの要素を取得するための最良の方法は何ですか1
これは for ループを使用せずに可能ですが、stl メソッドを使用することはできますか?

std::vector<float> myResult;            // contains: 1,2,5,7

ありがとうございました!

4

5 に答える 5

4

ここでは、STL アルゴリズムよりも単純な for ループの方が明らかに好まれます。

しかし、概念の証明として、stl::equals と C++11 のラムダをここで採用することができます。

std::equal(myVec.begin(), myVec.end(), markedToBeRead.begin(), [&](float item, int mark)->bool {
    if (mark)
        myResult.push_back(item);
    return true;
});

これは機能しますが、見栄えが悪くなります。

于 2012-06-19T10:23:34.037 に答える
3

このためのアルゴリズムを書く方法は次のとおりです。

template <typename I, typename O, typename M>
void mask_copy(I begin, I end, O obegin, M mbegin) {
    for (; begin != end; ++begin, ++mbegin)
        if (*mbegin)
            *obegin++ = *begin;
}

このように呼び出されます:

int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 , 9 };
bool m[] = { true, false, false, false, true, false, false, true, false };

std::vector<int> out;
mask_copy(begin(a), end(a), back_inserter(out), begin(m));

std::begin(とには C++11 が必要std::endです。)

とは言っても、ライブラリでの適切な実装では、使用される反復子の型がその使用と互換性があることを保証するためにenable_if(or ) を使用する可能性があります。つまり、入力反復子、互換性のある出力反復子、およびが 残念ながら、概念が欠けていると、これは真のテンプレートの「爆発」につながります。static_assertIOMvalue_typebool

于 2012-06-19T10:58:44.310 に答える
2

機能的に言​​えば、これは単純です。これは、2 つの入力範囲の zip であり、その後にマーク 1 のフィルターが続き、その後に値だけを抽出するためのマップが続きます。

残念ながら、C++ 標準アルゴリズムは合成にはあまり適していません。中間コンテナの作成を気にしない場合は、バイナリ バージョンの を適用しtransform、その後にcopy_if(またはremove_copy_ifC++03 では、述語を逆にするかremove_if、中間コンテナを適切に変更して)、その後に単項バージョンの を適用できtransformます。

あるいは、Boost は最初の 2 つの操作を反復子アダプターの形式で提供します。このようなもの(テストされていません):

struct marked {
    bool operator()(boost::tuple<int, float> t) {
        return t.get<0>() == 1;
    }
};

auto first = boost::make_zip_iterator(boost::make_tuple(markedToBeRead.begin(), myVec.begin());
auto last = boost::make_zip_iterator(boost::make_tuple(markedToBeRead.end(), myVec.end());

std::transform(
    boost::make_filter_iterator<marked>(first, last),
    boost::make_filter_iterator<marked>(last, last),
    std::back_inserter(myResults);
    [](boost:tuple<int, float> t) { return t.get<1>(); }
);

おそらく、(a) ループの方が優れていること、(b) ループを他の構造に置き換えることは、C++ では観戦スポーツのようなものであると確信しているでしょう ;-)

さらに操作を連鎖させる必要がある場合はstd::transform、 をイテレータ アダプタに置き換えることもできますtransform_iterator

于 2012-06-19T11:08:42.070 に答える
2

このようなもの?

for (unsigned int i = 0; i < myVec.length(); i++)
    if (markedToBeRead[i] == 1)
        myResult.push_back(myVec[i]);
于 2012-06-19T09:57:06.333 に答える
0

これは私のために働きます:

#include <algorithm>
#include <iostream>
#include <vector>

int main()  {
        std::vector<int>   markedToBeRead = {  1,1,0,0,1,0,1 };
        std::vector<float> myVec = { 1, 2, 3, 4, 5, 6, 7};

        // copy
        std::vector<float> result;
        std::copy_if(myVec.begin(), myVec.end(),
                std::back_inserter(result), [&](const float & f) {
                        return markedToBeRead[&f - &myVec[0]] == 1;
                });

        // Check result
        for (std::vector<float>::size_type i = 0; i < result.size(); ++i)
                std::cout << result[i] << " ";
}

Ideoneでテスト済み。

于 2012-06-19T11:12:15.357 に答える