web-dev-qa-db-ja.com

与えられたキーがC++のstd :: mapに存在するかどうかを調べる方法

与えられたキーがマップ内にあるかどうかを確認しようとしていますが、それができないことがあります。

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の内容を印刷するにはどうすればよいでしょうか。

map::find を使用

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

マップ内の特定のキーが存在するかどうかを確認するには、以下のいずれかの方法でcountメンバー関数を使用します。

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

documentationmap::findには、「別のメンバ関数map::countを使って、特定のキーが存在するかどうかだけを調べることができる」と書かれている。

documentationmap::countには、「マップコンテナ内のすべての要素は一意であるため、1(要素が見つかった場合)または0(それ以外の場合)のみを返すことができます。」

存在することがわかっているキーを介してマップから値を取得するには、 map :: at を使用します。

value = m.at(key)

map :: operator [] とは異なり、指定されたキーが存在しない場合、map::atはマップ内に新しいキーを作成しません。

279
DavidRR

.find()を使うことができます:

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

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

他のAPIを使用したい場合は、go for 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";
13
aJ.

map::findがほしいと思います。 m.find("f")m.end()と等しい場合、キーは見つかりませんでした。そうでなければ、findは見つかった要素を指すイテレータを返します。

このエラーは、p.firstがイテレータであるために発生します。これはストリームの挿入には使用できません。最後の行をcout << (p.first)->first;に変更してください。 pはイテレーターのペア、p.firstはイテレーター、p.first->firstはキー・ストリングです。

マップは与えられたキーに対して一つの要素しか持てないので、equal_rangeはあまり役に立ちません。それはすべての連想コンテナのために定義されているので、それはマップのために定義されていますが、それはマルチマップのためにはるかに面白いです。

12
Steve Jessop

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";
    }
}
6
Denis Sablukov
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.firstであるため、map<string, string>のオーバーロードが原因で発生したエラーは、印刷できません。これを試して:

if(p.first != p.second) {
    cout << p.first->first << " " << p.first->second << endl;
}
4
hustljian
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"は厄介で、私は頭の上から何かもっと思い付くことはできません...

4
Lambage

すべての答えはmap :: iterator i = m.find( "f");で行われているため、検索結果と末尾の結果を比較するときは、map 'm'のように注意してください。

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

m.end()と等しい場合、イテレータiでキーや値を出力するなどの操作を実行してはいけません。そうでないと、セグメンテーション違反が発生します。

3
Invictus

C++17If statement with initializerでこれをもう少し単純化しました。この方法であなたはあなたのケーキを持ってそれを食べることもできます。

if ( auto it{ m.find( "key" ) }; it != std::end( m ) ) 
{
    // Destructure the returned pair in to 
    // its sub components. Get them by reference.
    // You can also get them by 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..
}
1
WBuck

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
Hope