简体   繁体   English

std::map find_if 条件样式混淆

[英]std::map find_if condition style confusion

I'd like to use std::find_if to search for the first element in my map that has a certain value in a specific element of its value structure.我想使用std::find_if在我的地图中搜索在其值结构的特定元素中具有特定值的第一个元素。 I'm a little confused though.我有点困惑。 I think I need to use bind1st or bind2nd, but I'm not positive that's the right way to go.我想我需要使用 bind1st 或 bind2nd,但我不确定这是正确的方法。

Here's some pseudo-code:这是一些伪代码:

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(), <?>); 

So, let's say that I wanted to find the first element of the map where the .x member of the ValueType was equal to a certain integer value (which can change each call).所以,假设我想找到地图的第一个元素,其中 ValueType 的 .x 成员等于某个整数值(可以更改每次调用)。

What would be the best way to write a function or function object to achieve this?编写函数或函数对象来实现这一目标的最佳方法是什么? I understand that the <?> has to be a unary predicate which makes me think I'll need bind1st or bind2nd to provide the integer value I'm checking for, but I'm not sure how to go about it.我知道 <?> 必须是一元谓词,这让我觉得我需要 bind1st 或 bind2nd 来提供我正在检查的整数值,但我不确定如何去做。 It's been way too long since I looked at this stuff!好久没看这个东西了! >.< >.<

You can use a lambda function您可以使用 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;
   }
);

But as Kirill V. Lyadvinsky answer suggests the "first" element may not be what you expect.但正如 Kirill V. Lyadvinsky 的回答所暗示的那样,“第一”元素可能不是您所期望的。

Elements in the map are not sorted by value, they are sorted according to the key. map中的元素不是按值排序的,而是按键排序的。 So the phrase "the first element" has not much sense.所以“第一要素”这个词没有多大意义。

To find some element (not the first) that has x equal to some value you can write the functor as follows:要找到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_;
};

Then use it as follows:然后按如下方式使用它:

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

For the lazy, use a C++17 auto lambda, then you don't need to be verbose with the type.对于懒惰的人,请使用 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));

Building on all the answers above I cheat by using decltype with C++11 semantics.基于上述所有答案,我通过使用带有 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.
}

This doesn't have anything to do with std::bind1st or std::bind2nd .这与std::bind1ststd::bind2nd没有任何关系。 First of all, you have to keep in mind that the elements of a map are key-value pairs, in your case std::pair<int,ValueType> .首先,您必须记住,地图的元素是键值对,在您的情况下为std::pair<int,ValueType> Then you just need a predicate that compares the x member of the second member of yuch a pair against a specific value:然后您只需要一个谓词,将 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以免变慢?

using Boost.Bind and Boost.Lambda :使用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