在地图上使用find_if按值查找

时间:2010-12-23 15:45:58

标签: c++ stl

我有一个有地图的班级。我需要通过搜索特定值,密钥的instad来在map中找到迭代器。使用成员函数谓词IsValueFound,我正在尝试这个。

class A
{
public:
  void findVal();
private:
 int state;
 map<int, int> exmap;
 bool IsValueFound(pair<int key, int val> itr)
 {
   return state == itr.second;
 }
};

void A::findVal
{
  itr = find_if(exmap.begin, exmap.end, mem_fun1_ref(&A::IsValueFound));
}

我遇到了编译错误。我不确定这些功能适配器的语法是什么。请帮忙。

编辑:抱歉。请忽略finf_if stmt以外的编译错误。我需要先修改find​​_if stmt。代码也没有提升:(

7 个答案:

答案 0 :(得分:4)

将对象A转换为仿函数更容易:
但是您的代码还存在其他问题(见下文):

#include <map>
#include <memory>
#include <functional>
#include <algorithm>

using namespace std;

class A {
    public:
      void findVal();
    private:
      int state;
      map<int, int> exmap;

      // Changed the function IsValueFound() to operator()
      // This makes the whole object behave like a function.
      // Its a lot easier then getting member functions and binding
      // the this reference.
      bool operator()(map<int,int>::value_type const& itr) const
                    //         ^^^^^^^^^^^^^^^^^
                    //  std::pair<int,int> is not the type held in the map
                    //  so you are not going to bind against it using a pair.
      {
          return state == itr.second;
      }
};

void A::findVal()
{
    // You did not specify a type
    // for the iterator in your code.
    std::map<int,int>::iterator itr1 = find_if(exmap.begin(), exmap.end(), *this);
                                                   //   ^^^^^^       ^^^^^^
                                                   // begin() and end() are methods.

    // Just pass the `this` object as the the third parameter it will act as a function now.
}

答案 1 :(得分:3)

修改:我的答案显然有错误mem_fun1_ref(&A::IsValueFound)不能用作std::find_if的谓词。我正在努力纠正这个问题。

您忘记了exmap.beginexmap.end的括号。 我想如果你已经阅读了编译错误报告,它会告诉它一些事情。

我会这样写:

typedef map<int, int>::const_iterator MyIterator
void A::findVal()
{
    const MyIterator itrBegin = exmap.begin();
    const MyIterator itrEnd = exmap.end();
    MyIterator itrFound = find_if( itrBegin ,
                                   itrEnd ,
                                   mem_fun1_ref(&A::IsValueFound));    
}

但我没有尝试mem_fun1_ref(&A::IsValueFound)进行编译。而且我不习惯使用mem_fun1_ref,我总是用operator()重新定义我自己的仿函数。

答案 2 :(得分:2)

如果您不想使用Boost Bimap,您可以创建一个所谓的仿函数,一个重载函数调用操作符()的对象。在这段代码中:

class A {
public:
bool findVal(int s);

private:
map<int, int> exmap;

struct IsValueFound {
    int state;
    IsValueFound(int _state) : state(_state) {};
    bool operator()(const pair<int, int>& itr) {
        return state == itr.second;
    }
};  

};

bool A::findVal(int x) {
    return (find_if(exmap.begin(), exmap.end(), A::IsValueFound(x)) != exmap.end());
}

答案 3 :(得分:1)

至于编译错误,你在IsValueFound的参数列表中声明你的迭代器是错误的。它应该是:

map<int, int>::iterator itr

然后在A :: findVal中根本没有声明它。

话虽如此,如果您需要经常这样做,扫描地图中的值并不是一个好主意。您应该考虑数据的其他内部表示。

答案 4 :(得分:1)

mem_fun_ref采用你的一个参数函数

bool IsValueFound(pair<int, int> itr)

并将其转换为两个参数仿函数:

bool functor(A& this, pair<int, int> itr)

其中用作第一个参数的引用用于生成this指针以调用成员函数IsValueFound

你可能不希望这里有任何mem_fun_ref - 绑定器可以正常工作:

std::find_if(exmap.begin, exmap.end, std::bind2nd(std::equal_to<int>(), state));

刚才意识到这对地图迭代器不起作用......我可能只是在这一点上编写一个显式循环。

你也有一些语法错误,但是@martona已经触及了它们,所以我不会打败死马:)

答案 5 :(得分:0)

您实际上将地图用作bi-directional map,因此您可能会发现提升Boost Multi-index Containers非常有用。他们有一个实现双向地图的具体例子。

答案 6 :(得分:0)

只需使用Boost Bimap