std :: map find_if条件样式混乱

时间:2011-11-08 16:55:34

标签: c++ stl

我想使用std :: find_if来搜索我的地图中第一个在其值结构的特定元素中具有特定值的元素。我虽然有点困惑。我想我需要使用bind1st或bind2nd,但我并不认为这是正确的方法。

这是一些伪代码:

struct ValueType { int x, int y, int z };

std::map<int, ValueType> myMap;

... {populate map}

std::map<int, ValueType>::iterator pos = std::find_if(myMap.begin(), myMap.end(), <?>); 

所以,让我们说我想找到地图的第一个元素,其中ValueType的.x成员等于某个整数值(可以改变每个调用)。

编写函数或函数对象来实现此目的的最佳方法是什么?我知道必须是一个一元谓词,这让我觉得我需要bind1st或bind2nd来提供我正在检查的整数值,但我不知道如何去做。自从我看到这些东西以来,已经太久了! &GT;。&LT;

8 个答案:

答案 0 :(得分:20)

您可以使用lambda函数

int val = ...;
auto it = std::find_if(myMap.begin(), myMap.end(), 
   [val](const std::pair<int, ValueType> & t) -> bool { 
      return t.second.x == val;
   }
);

但正如Kirill V. Lyadvinsky的回答所暗示的那样,“第一”元素可能不是你所期望的。

答案 1 :(得分:18)

地图中的元素不按值排序,它们根据键进行排序。所以短语&#34;第一个元素&#34;没有多大意义。

要查找某个元素(不是第一个)x等于某个值,您可以按如下方式编写仿函数:

struct check_x
{
  check_x( int x ) : x_(x) {}
  bool operator()( const std::pair<int, ValueType>& v ) const 
  { 
    return v.second.x == x_; 
  }
private:
  int x_;
};

然后按如下方式使用:

// find any element where x equal to 10
std::find_if( myMap.begin(), myMap.end(), check_x(10) );

答案 2 :(得分:3)

struct Pred
{
    Pred(int x) : x_(x) { }
    bool operator()(const std::pair<int, ValueType>& p)
    {
        return (x_ == p.second.x);
    }
private:
    int x_;
};

... = std::find_if(myMap.begin(), myMap.end(), Pred(NUMBER));

答案 3 :(得分:2)

对于懒惰的人,请使用C ++ 17自动lambda,然后就不必在类型上太冗长了。

const auto it = std::find_if(myMap.begin(), myMap.end(), [&val](const auto &it) { 
      return it.second.x == val; // Comparing with the object
   }
);

答案 4 :(得分:1)

如果您还要在值中搜索,那么最好使用Boost Bimap以便不要慢?

答案 5 :(得分:1)

这与std::bind1ststd::bind2nd没有任何关系。首先,您必须记住,在您的案例std::pair<int,ValueType>中,地图的元素是键值对。那么你只需要一个谓词,将一对的第二个成员的x成员与特定值进行比较:

struct XEquals : std::unary_function<std::pair<int,ValueType>,bool>
{
    XEquals(int _x)
        : x(_x) {}
    bool operator()(const std::pair<int,ValueType> &v) const
        { return p.second.x == x; }
    int x;
};

答案 6 :(得分:1)

使用 Boost.Bind Boost.Lambda

...
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
...
typedef std::map<int, ValueType> MapType;
...
MapType::iterator pos = std::find_if(myMap.begin(), myMap.end(), 
    boost::bind(&ValueType::y, boost::bind(&MapType::iterator::value_type::second, _1)) == magic_number);

答案 7 :(得分:1)

基于上面的所有答案,我使用带有C ++ 11语义的decltype作弊。

auto beg_ = myMap.begin();
auto end_ = myMap.end();
auto it = find_if(beg_, end_,
    [&some_val](decltype(*beg_) & vt) {
        return vt.second == some_val;});
if (end_ != it) {
    auto key_found = (*it).first;
} else {
    // throw error not found.
}