std :: map find_if条件样式混乱

Joh*_*0te 13 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(), <?>); 
Run Code Online (Sandbox Code Playgroud)

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

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

Tyl*_*man 21

您可以使用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;
   }
);
Run Code Online (Sandbox Code Playgroud)

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


Kir*_*sky 19

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

要找到一些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_;
};
Run Code Online (Sandbox Code Playgroud)

然后使用如下:

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

  • 由于地图中的元素按键排序,因此条目的顺序是明确定义的,因此要求第一个满足条件的元素也是明确定义的. (4认同)

Al *_*rad 5

基于上述所有答案,我通过使用具有 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.
}
Run Code Online (Sandbox Code Playgroud)


小智 5

对于懒惰的人,请使用 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
   }
);
Run Code Online (Sandbox Code Playgroud)