यदि C ++ std :: मैप में दी गई कुंजी मौजूद है तो कैसे पता करें


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

तो मैं कैसे प्रिंट कर सकता हूं जो पी में है?


std::pair<iterator,bool> insert( const value_type& value );वह कौन सा बूल लौटाता है? यह बताता है, यदि कुंजी पहले से मौजूद है या नहीं?
कृतिकागोपालकृष्णन

जवाबों:


692

उपयोग map::find

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

105
यदि आप यह जांचना चाहते हैं कि क्या एक निश्चित कुंजी मौजूद है, तो आप शायद उपयोग करेंगेmap::count
tomsmeding

10
@tomsmeding एक std :: मानचित्र में केवल एक ही कुंजी है। तो गिनती या तो 0 होगी या 1. एक दूसरे की तुलना में अधिक कुशल है?
गोएलकैश

34
@goelakash शायद ही; यह सिर्फ है कि countरिटर्न एक int, जबकि findएक पूरे iterator देता है। आप पुनरावृत्ति के निर्माण को बचाते हैं :) जाहिर है, यदि आप बाद में मान का उपयोग करने जा रहे हैं यदि यह मौजूद है, तो इस परिणाम को ढूंढें और संग्रहीत करें।
tomsmeding

9
@tomsmeding यदि आप एक मल्टीमैप का उपयोग कर रहे हैं, तो आपको पूरे कंटेनर को देखना होगा। जिस स्थिति में, खोज () जल्दी हो सकती है।
ट्रेवर हिक्की

11
उन लोगों के लिए जो गति की तलाश कर रहे हैं: count और findअद्वितीय कुंजियों की आवश्यकता वाले नक्शे का उपयोग करते समय गति में लगभग समान हैं। (1) यदि आपको किसी विशिष्ट आदेश को बनाए रखने के लिए तत्वों की आवश्यकता नहीं है, तो std :: unordered_map का उपयोग करें , जिसमें निकट-स्थिर लुक-अप है और कुछ जोड़े से अधिक स्टोर करने पर यह बहुत फायदेमंद हो सकता है। (२) यदि आप मौजूद हैं तो मान का उपयोग करना चाहते हैं, :: के परिणाम को स्टोर करें: २ लुक-अप को रोकने के लिए auto it = m.find("f"); if (it != m.end()) {/*Use it->second*/}
पुनरावृत्त

305

यह जाँचने के लिए कि क्या मानचित्र में कोई विशेष कुंजी मौजूद है, countनिम्न में से किसी एक में सदस्य फ़ंक्शन का उपयोग करें :

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

प्रलेखन के लिए map::findकहते हैं: "एक और सदस्य समारोह, map::count, बस की जांच के लिए एक विशेष कुंजी मौजूद है या नहीं करने के लिए इस्तेमाल किया जा सकता।"

प्रलेखन के लिए map::countकहते हैं: "क्योंकि एक नक्शे के कंटेनर में सभी तत्वों को अद्वितीय हैं, समारोह केवल 1 लौट सकते हैं (यदि तत्व पाया जाता है) या शून्य (अन्यथा)।"

उस कुंजी के माध्यम से मानचित्र से एक मान प्राप्त करने के लिए जिसे आप अस्तित्व में जानते हैं, मानचित्र का उपयोग करें :: at :

value = m.at(key)

मानचित्र के विपरीत :: ऑपरेटर [] , map::atनक्शे में एक नई कुंजी नहीं बनाएगा यदि निर्दिष्ट कुंजी मौजूद नहीं है।


33
यदि आप दोनों ऑपरेशन करने जा रहे हैं, तो देखें कि क्या यह मौजूद है और फिर इसके बारे में कुछ करें। findइसके बजाय उपयोग करें । secondद्वारा लौटाए गए पुनरावृत्ति की विशेषता का findउपयोग कुंजी के मूल्य को पुनः प्राप्त करने के लिए किया जा सकता है। यदि आप countतब उपयोग करते हैं atया operator[]आप दो ऑपरेशन कर रहे हैं जब आप केवल एक का उपयोग कर सकते थे।
OdraEncoded

1
आपको> 0, == 1 या! = 0 करने की आवश्यकता नहीं है; एक सटीक बयान (स्थिति! = 0) में सटीक चेक C ++ करता है, तो आप बसif(m.count(key))
jv110 का

6
@ jv110 Microsoft C ++ कंपाइलर एक चेतावनी जारी करता है जब वह किसी कास्ट से intका सामना करता है bool। हालांकि अन्य C ++ कंपाइलर हैं जो समान चेतावनी जारी नहीं करते हैं, मैं इरादा स्पष्ट करने और पठनीयता बढ़ाने के लिए एक स्पष्ट तुलना का उपयोग करना पसंद करता हूं । ध्यान दें कि सूक्ष्म प्रोग्रामिंग त्रुटियों को शुरू करने की संभावना को रोकने के लिए सी # जैसी अन्य भाषाएं इस तरह के एक अंतर्निहित रूपांतरण को रोकती हैं।
डेविड आरआर

गिनती की समय जटिलता क्या है? क्या यह सिर्फ ओ (1) ऑपरेशन है?
माज़री

1
@Mazeryt यह देखते हुए कि हम C ++ मानक पुस्तकालय में एक वर्ग के बारे में बात कर रहे हैं, मैं निश्चित रूप से ऐसा मानूंगा। अपने प्रश्न की भाषा-अज्ञेय चर्चा के लिए, क्या वास्तव में हे (1) टेबल हैश हो सकता है?
डेविड आरआर

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

34
मुझे लगता है कि मैं इसे कहूंगा: अंत में।
एरिक कैम्पोबाडल

2
समय के बारे में .....
रिधुदर्शन

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 

यदि आप अन्य एपीआई का उपयोग करना चाहते हैं, तो इसके लिए जाएं 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(), तो चाबी नहीं मिली। अन्यथा, पाए गए तत्व को इंगित करने वाला एक पुनरावृत्‍ति खोजें।

त्रुटि इसलिए है क्योंकि p.firstयह एक पुनरावृत्ति है, जो स्ट्रीम सम्मिलन के लिए काम नहीं करता है। अपनी अंतिम पंक्ति बदलें cout << (p.first)->first;pपुनरावृत्तियों की एक जोड़ी है, p.firstएक पुनरावृत्ति p.first->firstहै, कुंजी स्ट्रिंग है।

एक मानचित्र में किसी दिए गए कुंजी के लिए केवल एक तत्व हो सकता equal_rangeहै , इसलिए यह बहुत उपयोगी नहीं है। यह मानचित्र के लिए परिभाषित है, क्योंकि यह सभी सहयोगी कंटेनरों के लिए परिभाषित है, लेकिन यह मल्टीमैप के लिए बहुत अधिक दिलचस्प है।


दरअसल, क्योंकि यह नक्शे में चलने वालों की एक जोड़ी है, इसलिए इसे "cout << p.first-> पहले" होना चाहिए;
स्टेफानव

मैंने अपना जवाब तय कर दिया है, धन्यवाद। मुझे अपना कोड संकलित नहीं करने के लिए मिलता है। और आप सही हैं (हटाए गए टिप्पणी में) वैधता की जाँच के बारे में, लेकिन मैं सिर्फ यह समझाने की कोशिश कर रहा था कि वह p.first क्यों नहीं छाप सकता है, और यह इसलिए नहीं है क्योंकि यह अमान्य है - हम जानते हैं कि "f" मिल जाएगा। चूँकि मैं बिल्कुल भी समान_का उपयोग करने की सलाह नहीं देता, इसलिए मैं उसके लिए त्रुटि-जाँच कोड दिखाने वाला नहीं हूँ।
स्टीव जेसप

वाह, आप वास्तव में एसओ को स्कैन कर रहे हैं। मैं इसे पूर्णता के लिए जोड़ रहा था, क्योंकि आपकी बात स्पष्ट थी। मैंने अपने पिछले उत्तर में वैधता जांच को जोड़ा, लेकिन आपकी प्रतिक्रिया ने मुझे धोखा दिया, इसलिए मैंने इसे हटा दिया, क्योंकि यह वैसे भी नहीं जोड़ा गया, जैसा आपने उल्लेख किया है।
स्टेफानव

हां, मैंने इसे केवल इसलिए देखा क्योंकि जब मैंने मेरी पोस्ट की तो आपकी टिप्पणी दिखाई दी।
स्टीव जेसप

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.first है map<string, string>, तो आप इसे प्रिंट नहीं कर सकते। इसे इस्तेमाल करे:

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

1
आपके पास एक टाइपो है। "काउंट" को "काउंट" में बदलें
रिवका

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

मानचित्र 'एम' के लिए अंतिम परिणाम की तरह खोज परिणाम की तुलना करने में सावधानी बरतें क्योंकि सभी उत्तर मानचित्र के ऊपर किए गए हैं: इट्रेटर i = m.find ("एफ");

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

आपको किसी भी ऑपरेशन को करने की कोशिश नहीं करनी चाहिए, जैसे कि कुंजी या मान को इटरेटर के साथ प्रिंट करना, अगर इसके बराबर m.end () है तो यह विभाजन दोष को जन्म देगा।


0

Std के कोड की तुलना :: नक्शा :: ढूँढें और 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::mapऔर std::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 में यह क्षमता पहले से है। इसके लिए दो डेटा संरचनाओं के बीच तुल्यकालन की भी आवश्यकता होगी जो एक निर्भरता है जिससे कोई भी निपटना नहीं चाहता है।
लम्बे

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

3
कृपया अपने कोड पर विस्तृत करें। बिना किसी स्पष्टीकरण के एक स्निपेट लंबे समय में सहायक नहीं होता है।
IBug
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.