지도에 키 값이 포함되어 있는지 확인 하시겠습니까?


256

STL 맵에 주어진 키의 값이 포함되어 있는지 확인하는 가장 좋은 방법은 무엇입니까?

#include <map>

using namespace std;

struct Bar
{
    int i;
};

int main()
{
    map<int, Bar> m;
    Bar b = {0};
    Bar b1 = {1};

    m[0] = b;
    m[1] = b1;

    //Bar b2 = m[2];
    map<int, Bar>::iterator iter = m.find(2);
    Bar b3 = iter->second;

}

이것을 디버거에서 검사하면 iter가비지 데이터 처럼 보입니다 .

이 줄을 주석 해제하면 :

Bar b2 = m[2]

디버거는이 표시 b2됩니다 {i = 0}. (정의되지 않은 인덱스를 사용하면 모든 비어 있거나 초기화되지 않은 값을 가진 구조체가 반환된다는 것을 의미한다고 생각합니다.)

이 방법들 중 어느 것도 그렇게 훌륭하지 않습니다. 내가 정말로 원하는 것은 다음과 같은 인터페이스입니다.

bool getValue(int key, Bar& out)
{
    if (map contains value for key)
    {
        out = map[key];
        return true;
    }
    return false;
}

이 선들을 따라 뭔가 존재 하는가?


답변:


274

이 선들을 따라 뭔가 존재 하는가?

아니요. stl map 클래스를 사용 ::find()하면 맵을 검색하고 반환 된 반복자와std::map::end()

그래서

map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
   //element found;
   b3 = it->second;
}

분명히 getValue()원하는 경우 (C ++에서도 사용할 이유가 없습니다) 자신의 루틴을 작성할 수 는 out있지만 사용 중단이 생기면 std::map::find()시간을 낭비하고 싶지 않을 것입니다.

또한 코드가 약간 잘못되었습니다.

m.find('2'); 키 값을 찾기 위해지도를 검색합니다. '2' . IIRC C ++ 컴파일러는 '2'를 암시 적으로 int로 변환하므로 원하는 '2'에 대한 ASCII 코드의 숫자 값이 생성됩니다.

이 예에서 키 유형은 다음 int과 같이 검색하려고합니다.m.find(2);


7
어떻게 요? find의도보다 훨씬 더 나은 의도를 나타냅니다 count. 더 이상, count항목을 반환하지 않습니다. 당신은 OP의 질문을 읽는다면, 그는 존재하지 않는지 확인하고 싶은 것 하고 요소를 반환합니다. find것을 수행. count하지 않습니다.
Alan

만약 (m.count (key)) b3 = m [key]; // 또는 무엇이든
pconnell

61
나는 항상 어떤 종류의 잡초가 전체 API를 디자인 한 사람들을 흡연하고 있는지 궁금했습니다.
Trap

2
Alan 나는 이것에 대해 @dynamic에 동의해야합니다. 반복자를 정의한 다음 그것을 end와 비교하는 것은 무언가 존재하지 않는다는 자연스러운 방법이 아닙니다. 이지도에서 특정 요소가 적어도 한 번은 나타나는 것이 훨씬 간단 해 보입니다. 어떤 것이 중요합니다.
PiersyP

1
@Claudiu C ++ 20은 그 점을 추가합니다.
pooya13

330

맵이 멀티 맵이 아닌 한 가장 우아한 방법 중 하나는 count 메소드를 사용하는 것입니다.

if (m.count(key))
    // key exists

요소가 실제로지도에 존재하면 개수는 1입니다.


22
키를 이미 찾았더라도 모든 키를 확인하지 않습니까? 그것은 비싸 빨리 얻을 수 있습니다 ...
mmdanziger

35
멀티 맵에서 사용되는 경우 하나 이상의 키만 계산합니다.
Andrew Prock

14
@mmdanziger 아니요, 비싸지 않습니다 : cplusplus.com/reference/map/map/count 수는 로그의 크기입니다.
jgyou

28
열쇠가 존재하면 무엇? 이 시점에서 일반적으로 다른 검색에 대한 비용을 지불하고 (예 :를 사용하여 operator[]) 값을 얻으려고합니다 . find.NET의 TryGetValue시맨틱을 제공합니다. 거의 항상 여러분 (특히 OP)이 원하는 것입니다.
하드 슈나이더

2
@ 세린 이해했다. 릴리스에서 키가 누락 된 경우 map [key]가 새로 기본 구성 요소 값을 반환하므로 동작이 달라집니다.
Ohad Schneider

53

정확한 구문이 아닌 find만으로 이미 존재합니다.

if (m.find(2) == m.end() )
{
    // key 2 doesn't exist
}

값이 존재하는 경우 값에 액세스하려면 다음을 수행하십시오.

map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
    // key 2 exists, do something with iter->second (the value)
}

C ++ 0x 및 auto를 사용하면 구문이 더 간단합니다.

auto iter = m.find(2);
if (iter != m.end() )
{
    // key 2 exists, do something with iter->second (the value)
}

단순화하기 위해 새로운 메커니즘을 고안하는 대신 익숙해 지도록 권장합니다. 약간의 코드를 줄일 수도 있지만 그렇게하는 비용을 고려하십시오. 이제 C ++에 익숙한 사람들이 인식 할 수없는 새로운 기능을 소개했습니다.

이러한 경고에도 불구하고이를 구현하려면 다음을 수행하십시오.

template <class Key, class Value, class Comparator, class Alloc>
bool getValue(const std::map<Key, Value, Comparator, Alloc>& my_map, int key, Value& out)
{
    typename std::map<Key, Value, Comparator, Alloc>::const_iterator it = my_map.find(key);
    if (it != my_map.end() )
    {
        out = it->second;
        return true;
    }
    return false;
}

38

방금 C ++ 20 을 사용하면

bool std::map::contains( const Key& key ) const;

map이 key가있는 요소를 보유하면 true를 반환합니다 key.


마지막으로이 기능에 대한 답변입니다! (C ++ 20)
Samuel Rasquinha

드디어 ? 고마워, 그러나 거의 2 세입니다! ;-)
kebs


4

의 반환 값 확인 find에 대한을 end.

map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) { 
  // contains
  ...
}

1

다음 코드를 사용하여 getValue 함수를 작성할 수 있습니다.

bool getValue(const std::map<int, Bar>& input, int key, Bar& out)
{
   std::map<int, Bar>::iterator foundIter = input.find(key);
   if (foundIter != input.end())
   {
      out = foundIter->second;
      return true;
   }
   return false;
}

6 번 라인은 다음과 같아야합니다out = foundIter->second
Dithermaster

Kip의 답변을 올바르게 표시 out = foundIter->second하지 않고 수정했습니다.out = *foundIter
netjeff

1

다른 답변 중 일부를 간결하게 요약하면 다음과 같습니다.

C ++ 20을 아직 사용하지 않는 경우 고유 한 mapContainsKey함수를 작성할 수 있습니다 .

bool mapContainsKey(std::map<int, int>& map, int key)
{
  if (map.find(key) == map.end()) return false;
  return true;
}

mapvs unordered_map키와 다른 키 및 값 유형에 대한 많은 과부하를 피하려면 이것을 atemplate 기능으로 .

C++ 20나중에 사용 하는 경우 내장 contains기능이 있습니다.

std::map<int, int> myMap;

// do stuff with myMap here

int key = 123;

if (myMap.contains(key))
{
  // stuff here
}

-1

키가 맵에 있는지 여부를 판별하려면 map의 find () 또는 count () 멤버 함수를 사용할 수 있습니다. 예제에서 사용되는 find 함수는 반복자를 element 또는 map :: end에 반환합니다. count의 경우 카운트는 발견되면 1을 반환하고, 그렇지 않으면 0을 반환합니다.

if(phone.count(key))
{ //key found
}
else
{//key not found
}

for(int i=0;i<v.size();i++){
    phoneMap::iterator itr=phone.find(v[i]);//I have used a vector in this example to check through map you cal receive a value using at() e.g: map.at(key);
    if(itr!=phone.end())
        cout<<v[i]<<"="<<itr->second<<endl;
    else
        cout<<"Not found"<<endl;
}

-1

적절한 솔루션으로 Boost multindex를 사용할 수 있습니다. 다음 솔루션은 최상의 옵션은 아니지만 초기화시 사용자가 0 또는 NULL과 같은 기본값을 할당하고 값이 수정되었는지 확인하려는 경우에 유용 할 수 있습니다.

Ex.
< int , string >
< string , int > 
< string , string > 

consider < string , string >
mymap["1st"]="first";
mymap["second"]="";
for (std::map<string,string>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
       if ( it->second =="" ) 
            continue;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.