18

特定の値のみが含まれるように、ベクトルをフィルタリングしようとしています。

例: ベクトルに値 "abc" の要素のみが含まれていることを確認します。

現在、私は でこれを達成しようとしていremove_copy_ifます。

std のアルゴリズムの 1 つを使用するときに、述語に追加のパラメーターを渡す方法はありますか?

std::vector<std::string> first, second;
first.push_back("abc");
first.push_back("abc");
first.push_back("def");
first.push_back("abd");
first.push_back("cde");
first.push_back("def");

std::remove_copy_if(first.begin(), first.end(), second.begin(), is_invalid);

次の関数を述語として渡したいと思っていますが、現在の値と次の値を比較するだけで終わる可能性が高いようremove_copy_ifです。

bool is_invalid(const std::string &str, const std::string &wanted)
{
   return str.compare(wanted) != 0;
}

私はおそらくこれに間違ったアプローチをしていると感じているので、何か提案をいただければ幸いです!

ありがとう

4

2 に答える 2

23

代わりにファンクターを定義します。

struct is_invalid
{
    is_invalid(const std::string& a_wanted) : wanted(a_wanted) {}
    std::string wanted;
    bool operator()(const std::string& str)
    {
        return str.compare(wanted) != 0;
    }
};

std::remove_copy_if(first.begin(),
                    first.end(),
                    second.begin(),
                    is_invalid("abc"));

または C++11 がラムダを使用する場合:

std::string wanted("abc");
std::remove_copy_if(first.begin(), first.end(), second.begin(), 
    [&wanted](const std::string& str)
    {
        return str.compare(wanted) != 0;
    });

出力ベクトル は、 への呼び出しの前に要素を持たなければならないことに注意secondしてくださいremove_copy_if()

// Create 'second' after population of 'first'.
//
std::vector<std::string> second(first.size());

std::string wanted = "abc";
int copied_items    = 0;
std::remove_copy_if( first.begin(), first.end(), second.begin(),
    [&wanted, &copied_items](const std::string& str) -> bool
    {
        if (str.compare(wanted) != 0) return true;
        copied_items++;
        return false;
    });
second.resize(copied_items);

ファンクタ述語がコピーされると、copied_items情報を保持するためにより多くの労力が必要になります。推奨される解決策については、「 C++ で std algos 述語を参照によって渡す」を参照してください。

于 2012-11-23T08:33:53.190 に答える
10

functor を作成するか、 を使用しますstd/boost::bind

struct is_invalid
{
public:
   is_invalid(const std::string& w):wanted(w) { }
   bool operator () (const std::string& str)
   {
       return str.compare(wanted) != 0;
   }
private:
   std::string wanted;
};

std::remove_copy_if(first.begin(), first.end(), second.begin(), is_invalid("abc"));

バインドの例

bool is_invalid(const std::string &str, const std::string &wanted)
{
   return str.compare(wanted) != 0;
}

std::remove_copy_if(first.begin(), first.end(), second.begin(),
boost::bind(is_invalid, _1, "abc"));
于 2012-11-23T08:33:35.397 に答える