주어진 키가 C ++ std :: map에 있는지 확인하는 방법


451

주어진 키가 맵에 있는지 확인하고 다소 할 수 없습니다.

typedef map<string,string>::iterator mi;
map<string, string> m;
m.insert(make_pair("f","++--"));
pair<mi,mi> p = m.equal_range("f");//I'm not sure if equal_range does what I want
cout << p.first;//I'm getting error here

p에있는 내용을 어떻게 인쇄 할 수 있습니까?


std::pair<iterator,bool> insert( const value_type& value );그것이 반환되는 부울은 무엇입니까? 키가 이미 있는지 여부를 알려줍니까?
krithikaGopalakrisnan

답변:


692

사용하다 map::find

if ( m.find("f") == m.end() ) {
  // not found
} else {
  // found
}

105
당신은 단지 특정 키가 존재하는지 여부를 확인하려면, 당신은 아마 대신 사용하십시오map::count
tomsmeding을

10
@tomsmeding std :: map에는 하나의 키만 있습니다. 카운트는 0 또는 1입니다. 하나는 다른 것보다 더 효율적입니까?
골라 카시

34
@goelakash 거의; 그것 뿐이다 count다시 표시 int하면서이 find전체 반복자를 돌려줍니다. 반복자의 구성을 저장합니다. :) 나중에 값 을 사용 하려는 경우 find를 사용하여 결과를 저장하십시오.
tomsmeding

9
@tomsmeding 멀티 맵을 사용하는 경우 전체 컨테이너를 살펴 봐야합니다. 이 경우 find ()가 더 빠를 수 있습니다.
Trevor Hickey

11
: 속도를 찾는 사람들에게 countfind고유 키를 필요로지도를 사용할 때 속도가 거의 동일합니다. (1) 특정 순서, 사용 유지하기 위해 요소를 필요로하지 않는 경우 표준 :: unordered_map도 있고, 거의 일정한 모양 업을보다 몇 쌍 이상 저장할 때 매우 도움이 될 수 있습니다. (2) 존재하는 경우 값을 사용하려면 :: find의 결과를 저장하고 반복자를 사용하여 2 개의 조회를 방지하십시오.auto it = m.find("f"); if (it != m.end()) {/*Use it->second*/}
cdgraham

305

맵에 특정 키가 존재하는지 확인하려면 count다음 방법 중 하나로 멤버 함수를 사용하십시오 .

m.count(key) > 0
m.count(key) == 1
m.count(key) != 0

그만큼 문서 에는 map::find말한다 : "다른 멤버 함수는, map::count단지 특정 키가 존재하는지 여부를 확인하는 데 사용할 수 있습니다."

그만큼 문서 에는 map::count말한다 : "지도 컨테이너의 모든 요소가 고유하기 때문에 (요소가 발견되는 경우) 함수는 1을 반환 할 수 있습니다 또는 (기타) 제로."

존재하는 키를 통해지도에서 값을 검색하려면 map :: at을 사용하십시오 .

value = m.at(key)

달리 지도 : 연산자 [] , map::at지정된 키가 존재하지 않을 경우지도에 새로운 키를 생성하지 않습니다.


33
두 작업을 모두 수행하려는 경우 해당 작업이 존재하는지 확인한 후 이에 대해 무언가를 수행하십시오. find대신 사용하십시오 . 에 second의해 리턴 된 반복자 의 속성은 find키 값을 검색하는 데 사용될 수 있습니다. 당신이 사용하는 경우 count다음 at또는 operator[]당신이 하나의 사용할 수도 때 두 가지 작업을 수행한다.
OdraEncoded

1
> 0, == 1 또는! = 0을 수행 할 필요는 없습니다. 이것이 C ++이 if 문 (condition! = 0)에서 수행하는 정확한 검사이므로 다음과 같이 사용할 수 있습니다.if(m.count(key))
jv110

6
@ jv110 마이크로 소프트 C ++ 컴파일러 문제 경고 가에서 캐스트가 발생 int하는 bool. 비슷한 경고를 발행하지 않는 다른 C ++ 컴파일러가 있지만 의도를 명확하게하고 가독성을 높이기 위해 명시 적 비교 를 선호합니다 . C #과 같은 다른 언어 는 미묘한 프로그래밍 오류가 발생할 가능성을 방지하기 위해 이러한 암시 적 변환 을 금지합니다.
DavidRR

카운트의 시간 복잡성은 무엇입니까? O (1) 작동입니까?
Mazeryt

1
@Mazeryt C ++ 표준 라이브러리의 클래스에 대해 이야기하고 있다고 가정하면 확실히 그렇게 가정합니다. 질문에 대해 언어에 구애받지 않고 토론하려면 해시 테이블이 실제로 O (1) 일 수 있습니까?를 참조하십시오 . .
DavidRR

47

C ++ 20 은이 std::map::contains를 가능하게합니다.

#include <iostream>
#include <string>
#include <map>

int main()
{
    std::map<int, std::string> example = {{1, "One"}, {2, "Two"}, 
                                     {3, "Three"}, {42, "Don\'t Panic!!!"}};

    if(example.contains(42)) {
        std::cout << "Found\n";
    } else {
        std::cout << "Not found\n";
    }
}

35
내가 말할 것 같아 : 마지막으로.
Erik Campobadal

2
시간에 대해 .....
Ridhuvarshan

39

당신은 사용할 수 있습니다 .find():

map<string,string>::iterator i = m.find("f");

if (i == m.end()) { /* Not found */ }
else { /* Found, i->first is f, i->second is ++-- */ }

15
m.find == m.end() // not found 

다른 API를 사용하려면 다음을 찾으십시오. m.count(c)>0

 if (m.count("f")>0)
      cout << " is an element of m.\n";
    else 
      cout << " is not an element of m.\n";

12

당신이 원하는 것 같아요 map::find. 이 ( m.find("f")가) 같으면 m.end()키를 찾을 수 없습니다. 그렇지 않으면 find는 찾은 요소를 가리키는 반복자를 리턴합니다.

p.first스트림 삽입에는 작동하지 않는 반복자 이기 때문에 오류가 발생 합니다. 마지막 줄을로 변경하십시오 cout << (p.first)->first;. p반복자, p.first반복자, p.first->first키 문자열입니다.

지도는 주어진 키에 대해 하나의 요소 만 가질 수 있으므로 equal_range그다지 유용하지 않습니다. 모든 연관 컨테이너에 대해 정의되었으므로 맵에 대해 정의되었지만 멀티 맵에는 훨씬 더 흥미 롭습니다.


실제로, 맵에 대한 반복자 쌍이므로 "cout << p.first-> first;"이어야합니다.
stefaanv 2009

답변을 고쳤습니다. 감사합니다. 그것이 내 코드를 컴파일하지 않아 얻는 것입니다. 그리고 당신은 유효성을 검사하는 것에 대해 (삭제 된 의견으로) 옳습니다. 그러나 그가 왜 p.first를 인쇄 할 수 없었는지 설명하려고했습니다. 잘못된 것이 아니기 때문입니다. equal_range를 전혀 사용하지 않는 것이 좋으므로 오류 검사 코드를 표시하지 않습니다.
Steve Jessop

와우, 당신은 정말 스캔하고 있습니다. 당신의 요점이 분명했기 때문에 나는 그것을 완전성을 위해 그것을 추가하고있었습니다. 이전 답변에 유효성 검사를 추가했지만 응답이 저를 때렸으므로 언급했듯이 어쨌든 많이 추가하지 않았기 때문에 삭제했습니다.
stefaanv 2009

네, 내 의견을 게시했을 때 귀하의 의견이 나타났기 때문에 전혀 보지 못했습니다.
Steve Jessop

12

C++17으로 이것을 조금 더 단순화했습니다 If statement with initializer. 이렇게하면 케이크를 먹고 먹을 수 있습니다.

if ( auto it{ m.find( "key" ) }; it != std::end( m ) ) 
{
    // Use `structured binding` to get the key
    // and value.
    auto[ key, value ] { *it };

    // Grab either the key or value stored in the pair.
    // The key is stored in the 'first' variable and
    // the 'value' is stored in the second.
    auto mkey{ it->first };
    auto mvalue{ it->second };

    // That or just grab the entire pair pointed
    // to by the iterator.
    auto pair{ *it };
} 
else 
{
   // Key was not found..
}

4
map<string, string> m;

확인 키가 존재하고 반환 횟수가 발생합니다 (지도에서 0/1).

int num = m.count("f");  
if (num>0) {    
    //found   
} else {  
    // not found  
}

키가 있는지 확인하고 반복자를 리턴하십시오.

map<string,string>::iterator mi = m.find("f");  
if(mi != m.end()) {  
    //found  
    //do something to mi.  
} else {  
    // not found  
}  

귀하의 질문에, 잘못된 operator<<과부하로 인한 오류 p.firstmap<string, string>입니다. 이 시도:

if(p.first != p.second) {
    cout << p.first->first << " " << p.first->second << endl;
}

1
오타가 있습니다. "cout"을 "count"로 변경
Rivka

1
(가)로 그리고 오타 정말 누군가를 던질 수있는 cout것보다 매우 다른 것을 의미 할 수있다count
modulitos

4
template <typename T, typename Key>
bool key_exists(const T& container, const Key& key)
{
    return (container.find(key) != std::end(container));
}

물론 더 좋아지기를 원한다면 발견 된 기능과 발견되지 않은 기능을 취하는 함수를 항상 템플릿으로 만들 수 있습니다.

template <typename T, typename Key, typename FoundFunction, typename NotFoundFunction>
void find_and_execute(const T& container, const Key& key, FoundFunction found_function, NotFoundFunction not_found_function)
{
    auto& it = container.find(key);
    if (it != std::end(container))
    {
        found_function(key, it->second);
    }
    else
    {
        not_found_function(key);
    }
}

그리고 이것을 다음과 같이 사용하십시오 :

    std::map<int, int> some_map;
    find_and_execute(some_map, 1,
        [](int key, int value){ std::cout << "key " << key << " found, value: " << value << std::endl; },
        [](int key){ std::cout << "key " << key << " not found" << std::endl; });

이것의 단점은 좋은 이름으로 나오고 있습니다. "find_and_execute"는 어색하며 내 머리 꼭대기에서 더 나은 것을 만들 수는 없습니다 ...


3

모든 대답이 map 위에서 수행되었으므로 찾기 결과를 map 'm'과 같은 끝과 비교할 때주의하십시오. : iterator i = m.find ( "f");

 if (i == m.end())
 {
 }
 else
 {
 }  

m.end ()와 동일한 경우 iterator i를 사용하여 키 또는 값을 인쇄하는 등의 작업을 수행하지 않아야합니다. 그렇지 않으면 분할 오류가 발생합니다.


0

std :: map :: find 및 std :: map :: count 코드를 비교하면 첫 번째 성능 이점이 있다고 말할 수 있습니다.

const_iterator find(const key_type& _Keyval) const
    {   // find an element in nonmutable sequence that matches _Keyval
    const_iterator _Where = lower_bound(_Keyval); // Here one looks only for lower bound
    return (_Where == end()
        || _DEBUG_LT_PRED(this->_Getcomp(),
            _Keyval, this->_Key(_Where._Mynode()))
                ? end() : _Where);
    }

size_type count(const key_type& _Keyval) const
    {   // count all elements that match _Keyval
    _Paircc _Ans = equal_range(_Keyval); // Here both lower and upper bounds are to be found, which is presumably slower.
    size_type _Num = 0;
    _Distance(_Ans.first, _Ans.second, _Num);
    return (_Num);
    }

0

나는이 질문에 이미 좋은 답변이 있지만 내 솔루션이 공유 할 가치가 있다고 생각합니다.

그것은 모두를 위해 작동 std::mapstd::vector<std::pair<T, U>>와 C ++ 11에서 사용할 수 있습니다.

template <typename ForwardIterator, typename Key>
bool contains_key(ForwardIterator first, ForwardIterator last, Key const key) {
    using ValueType = typename std::iterator_traits<ForwardIterator>::value_type;

    auto search_result = std::find_if(
        first, last,
        [&key](ValueType const& item) {
            return item.first == key;
        }
    );

    if (search_result == last) {
        return false;
    } else {
        return true;
    }
}

-5

지도 쌍을 비교하려면이 방법을 사용할 수 있습니다.

typedef map<double, double> TestMap;
TestMap testMap;
pair<map<double,double>::iterator,bool> controlMapValues;

controlMapValues= testMap.insert(std::pair<double,double>(x,y));
if (controlMapValues.second == false )
{
    TestMap::iterator it;
    it = testMap.find(x);

    if (it->second == y)
    {
        cout<<"Given value is already exist in Map"<<endl;
    }
}

이것은 유용한 기술입니다.


C ++ 프로그래밍 초보자 로서이 답변이 다운 투표 된 이유가 정말 궁금합니다. 이 답변이 왜 인기가 없습니까?
gromit190

3
@ gromit190은 std :: map에 이미이 기능이있을 때 키가 존재하는지 확인하기 위해 완전히 다른 데이터 구조를 사용하고 있기 때문입니다. 또한 아무도 다루고 싶지 않은 두 데이터 구조 간의 동기화가 필요합니다.
Lambage

-5
map <int , char>::iterator itr;
    for(itr = MyMap.begin() ; itr!= MyMap.end() ; itr++)
    {
        if (itr->second == 'c')
        {
            cout<<itr->first<<endl;
        }
    }

3
코드를 자세히 설명하십시오. 설명이없는 스 니펫은 장기적으로 도움이되지 않습니다.
iBug
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.