2011-11-08 2 views
8

std :: find_if를 사용하여 값 구조의 특정 요소에 특정 값을 가진 내지도의 첫 번째 요소를 검색하고 싶습니다. 나는 조금 혼란 스럽다. bind1st 또는 bind2nd를 사용해야한다고 생각합니다. 그러나 나는 올바른 방법이 아닙니다. 하는 수 (std :: map find_if 조건 스타일 혼동

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

자, 내가 치형의 .x와 회원이 특정 정수 값과 동일했다 맵의 첫 번째 요소를 찾기 위해 싶다고 가정 해 봅시다 : 여기

은 일부 의사 코드입니다 각 통화 변경).

이것을 달성하기 위해 함수 또는 함수 객체를 작성하는 가장 좋은 방법은 무엇입니까? 나는 정수 값을 제공하기 위해 bind1st 나 bind2nd가 필요하다고 생각하게하는 단항 술어가되어야한다는 것을 이해합니다.하지만 그것에 대해 어떻게 해야할지 잘 모르겠습니다. 이 재료를봤을 때 너무 오랜 시간이 걸렸습니다! >. <

답변

15

지도의 요소는 값에 따라 정렬되지 않고 키에 따라 정렬됩니다. 따라서 "첫 번째 요소"라는 구절은별로 의미가 없습니다.

찾으려면 당신이 다음과 같이 펑터를 쓸 수있는 값과 동일한 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)); 
+3

지도의 요소는 키순으로 정렬되므로 입력 순서가 잘 정의되어 있으므로 조건을 충족하는 첫 번째 항목을 묻는 것이 잘 정의되어 있습니다. – celtschk

+0

예, 잘 정의되어 있습니다. 그러나 순서는 ValueType의 값에 종속되지 않습니다. 그게 내가 말하려고했던거야. –

+0

고마워, 정확히 내가 필요한 것 :) –

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

또한 값을 검색하려면 느린 속도가되지 않도록 Boost Bimap을 사용하는 것이 더 좋을 수 있습니다.

11

당신은 람다 함수를

int val = ...; 
auto it = std::find_if(myMap.begin(), myMap.end(), 
    [val](const std::pair<int, ValueType> & t) -> bool { 
     return t.second.x == val; 
    } 
); 

를 사용할 수 있지만 키릴 V. Lyadvinsky의 대답에서 알 수 있듯이 "첫 번째"요소는 무엇을 기대하지 않을 수 있습니다.

1

여기에는 std::bind1st 또는 std::bind2nd과 관련이 없습니다. 우선,지도의 요소는 키 - 값 쌍인입니다.

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

Boost.BindBoost.Lambda를 사용하여 : : 그럼 그냥 특정 값에 대한 yuch 한 쌍의 제 2 부재의 x 구성원을 비교하는 술어가 필요

... 
#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); 
1

위의 모든 답을 바탕으로 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. 
}