C++ std::map find_if 条件样式混淆

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8054147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:55:55  来源:igfitidea点击:

std::map find_if condition style confusion

c++stl

提问by John Humphreys - w00te

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. 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.

我想使用 std::find_if 在我的地图中搜索在其值结构的特定元素中具有特定值的第一个元素。我有点困惑。我想我需要使用 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. It's been way too long since I looked at this stuff! >.<

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

回答by Tyler Hyndman

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

回答by Kirill V. Lyadvinsky

Elements in the map are not sorted by value, they are sorted according to the key. So the phrase "the first element" has not much sense.

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

To find someelement (not the first) that has xequal 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) );

回答by John

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));

回答by Narek

If you want to search also in values then may be better to use Boost Bimapin order not to be slow?

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

回答by Christian Rau

This doesn't have anything to do with std::bind1stor std::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>. Then you just need a predicate that compares the x member of the second member of yuch a pair against a specific value:

这与std::bind1st或没有任何关系std::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;
};

回答by Andriy Tylychko

using Boost.Bindand 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);

回答by Al Conrad

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.
}

回答by Unkle George

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
   }
);