簡體   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