繁体   English   中英

std::map find_if 条件样式混淆

[英]std::map find_if condition style confusion

我想使用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 来提供我正在检查的整数值,但我不确定如何去做。 好久没看这个东西了! >.<

您可以使用 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 的回答所暗示的那样,“第一”元素可能不是您所期望的。

map中的元素不是按值排序的,而是按键排序的。 所以“第一要素”这个词没有多大意义。

要找到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) );

对于懒惰的人,请使用 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
   }
);
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));

基于上述所有答案,我通过使用带有 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.
}

这与std::bind1ststd::bind2nd没有任何关系。 首先,您必须记住,地图的元素是键值对,在您的情况下为std::pair<int,ValueType> 然后您只需要一个谓词,将 yuch a pair 的第二个成员的 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;
};

如果您还想在值中进行搜索,那么最好使用Boost Bimap以免变慢?

使用Boost.BindBoost.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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM