Hoe te vinden of een bepaalde sleutel bestaat in een C++ std::map

Ik probeer te controleren of een bepaalde sleutel op een kaart staat en kan het enigszins niet:

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

dus hoe kan ik afdrukken wat er in p staat?


Antwoord 1, autoriteit 100%

Gebruik map::find

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

Antwoord 2, autoriteit 42%

Om te controleren of een bepaalde sleutel in de kaart bestaat, gebruikt u de ledenfunctie count op een van de volgende manieren:

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

De documentatie voor map::find zegt: “Een andere ledenfunctie, map::count, kan worden gebruikt om te controleren of een bepaalde sleutel bestaat.”

De documentatie voor map::count zegt: “Omdat alle elementen in een kaartcontainer uniek zijn, kan de functie alleen 1 (als het element wordt gevonden) of nul (anders) retourneren.”

Als u een waarde van de kaart wilt ophalen via een sleutel waarvan u weet dat deze bestaat, gebruikt u kaart::at:

value = m.at(key)

In tegenstelling tot map::operator[], map::at maakt geen nieuwe sleutel in de kaart als de opgegeven sleutel niet bestaat.


Antwoord 3, autoriteit 11%

C++20 geeft ons std::map::contains om dat te doen.

#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";
    }
}

Antwoord 4, autoriteit 5%

U kunt .find() gebruiken:

map<string,string>::iterator i = m.find("f");
if (i == m.end()) { /* Not found */ }
else { /* Found, i->first is f, i->second is ++-- */ }

Antwoord 5, autoriteit 3%

C++17 vereenvoudigde dit een beetje meer met een If statement with initializer.
Op deze manier kun je je cake hebben en ook opeten.

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..
}

Antwoord 6, autoriteit 2%

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

Als je een andere API wilt gebruiken, ga dan voor 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";

Antwoord 7, autoriteit 2%

Ik denk dat je map::find wilt. Als m.find("f") gelijk is aan m.end(), dan is de sleutel niet gevonden. Anders retourneert find een iterator die wijst naar het gevonden element.

De fout is omdat p.first een iterator is, die niet werkt voor het invoegen van streams. Verander je laatste regel in cout << (p.first)->first;. p is een paar iterators, p.first is een iterator, p.first->first is de sleutelreeks.

Een kaart kan maar één element voor een bepaalde sleutel hebben, dus equal_range is niet erg handig. Het is gedefinieerd voor kaarten, omdat het is gedefinieerd voor alle associatieve containers, maar het is veel interessanter voor multimap.


Antwoord 8

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

Als je liefhebber wilt worden, kun je natuurlijk altijd een functie ontwerpen die ook een gevonden functie en een niet gevonden functie heeft, zoiets als dit:

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

En gebruik het als volgt:

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

Het nadeel hiervan is het bedenken van een goede naam, “find_and_execute” is onhandig en ik kan niets beters bedenken uit mijn hoofd…


Antwoord 9

map<string, string> m;

controleer of de sleutel bestaat of niet, en retourneer het aantal komt voor (0/1 op de kaart):

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

controleer of de sleutel bestaat of niet, en retourneer iterator:

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

in uw vraag, de fout veroorzaakt door een slechte operator<< overbelasting, omdat p.first map<string, string> is , kunt u het niet uitprinten. probeer dit:

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

Antwoord 10

Wees voorzichtig bij het vergelijken van het resultaat van de vondst met het einde zoals voor kaart ‘m’ zoals alle antwoorden hebben
hierboven gedaan
map::iterator i = m.find(“f”);

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

u moet niet proberen een bewerking uit te voeren, zoals het afdrukken van de sleutel of waarde met iterator i als deze gelijk is aan m.end() anders zal dit leiden tot een segmentatiefout.


Antwoord 11

Als ik de code van std::map::find en std::map::count vergelijk, zou ik zeggen dat de eerste wat prestatievoordeel kan opleveren:

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

Antwoord 12

Ik weet dat deze vraag al een aantal goede antwoorden heeft, maar ik denk dat mijn oplossing het delen waard is.

Het werkt voor zowel std::map als std::vector<std::pair<T, U>> en is beschikbaar vanaf 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;
    }
}

Antwoord 13

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

Antwoord 14

Als u een paar kaarten wilt vergelijken, kunt u deze methode gebruiken:

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

Dit is een nuttige techniek.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes