マップにキーの値が含まれているかどうかを確認しますか?


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マップクラスでは、を使用::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ではない。
アラン

if(m.count(key))b3 = m [key]; //または何でも
pconnell 2013

62
stl API全体を設計した人々がどのような雑草を吸っているのかについて、私は常に知りたいと思っていました。
2014年

2
アラン私はこれについて@dynamicに同意する必要があります。イテレータを定義してからそれをendと比較する必要があることは、何かが存在しないと言うのは自然な方法ではありません。特定の要素がこのマップに少なくとも1回出現すると言うのは、私にははるかに簡単です。これがカウントの機能です。
PiersyP 2017年

1
@Claudiu C ++ 20はまさにそれを追加します。
pooya13

330

マップがマルチマップでない限り、最もエレガントな方法の1つはcountメソッドを使用することです。

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

要素が実際にマップに存在する場合、カウントは1になります。


22
すでに1つ見つかった場合でも、すべてのキーをチェックませんか?それは速く高価になる可能性があります...
mmdanziger 2012年

35
マルチマップで使用した場合、複数のキーのみがカウントされます。
Andrew Prock 2013年

14
@mmdanzigerいいえ、高価ではありません。cplusplus.com/ reference / map / map / count カウントのサイズは対数です。
jgyou 2014年

28
キーが存在し、それから何ですか?その時点で、通常はその値を取得し、別の検索(例:を使用operator[])の料金を支払います。find.NETのTryGetValueセマンティクスを提供します。ほとんどの場合、これはユーザー(特にOP)が望んでいることです。
Ohad Schneider

2
@serineわかりました。リリースでキーが欠落している場合、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

の戻り値をチェックfindendます。

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
ディザマスターである

私は正確に表示するキップの答え固定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やさまざまなキーと値の型の多くのオーバーロードを回避したい場合は、これをaにすることができますtemplate関数にます。

C++ 20以降を使用している場合は、組み込みcontains関数があります。

std::map<int, int> myMap;

// do stuff with myMap here

int key = 123;

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

-1

キーがマップに存在するかどうかを判断する場合は、マップのメンバー関数find()またはcount()を使用できます。ここで例として使用されているfind関数は、イテレーターをelementまたはmap :: endに戻します。countの場合、見つかった場合、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.