मैं C ++ के नक्शे के माध्यम से कैसे लूप कर सकता हूं?


292

मैं std::mapC ++ में कैसे लूप कर सकता हूं ? मेरे नक्शे को इस प्रकार परिभाषित किया गया है:

std::map< std::string, std::map<std::string, std::string> >

उदाहरण के लिए, उपरोक्त कंटेनर इस तरह डेटा रखता है:

m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";

मैं इस नक्शे के माध्यम से कैसे लूप कर सकता हूं और विभिन्न मूल्यों तक पहुंच बना सकता हूं?


25
आप आधुनिक सी ++ के लिए दंगा के जवाब को स्वीकार करने पर विचार कर सकते हैं, इसे गोगलर्स के लिए कर सकते हैं।
सर्जियो बसुरको

पूरी तरह से निश्चित नहीं है कि नक्शों का एक नक्शा न्यूनतम, पूर्ण, सत्यापन योग्य उदाहरण होगा लेकिन बिंदु बनाया गया है!
davidhood2

3
यदि आपने नोटिफिकेशन याद किया है, तो मुझे चकली की टिप्पणी को दोहराने दें: आप आधुनिक c ++ के लिए दंगा के उत्तर को स्वीकार करने पर विचार कर सकते हैं, इसे गोगलर्स के लिए करें।
no --zɐɹƆ

पिल्ला का जवाब अधिक बहुमुखी है, लेकिन गुगलों की संख्या को देखते हुए, दंगा के जवाब को अधिक चाहते हैं।
लीजियन डेथ

जवाबों:


563

पुराना प्रश्न लेकिन शेष उत्तर C ++ 11 के रूप में पुराने हैं - आप लूप के लिए एक राउंडेड का उपयोग कर सकते हैं और बस कर सकते हैं:

std::map<std::string, std::map<std::string, std::string>> mymap;

for(auto const &ent1 : mymap) {
  // ent1.first is the first key
  for(auto const &ent2 : ent1.second) {
    // ent2.first is the second key
    // ent2.second is the data
  }
}

यह पहले के संस्करणों की तुलना में बहुत अधिक साफ होना चाहिए, और अनावश्यक प्रतियों से बचा जाता है।

कुछ संदर्भ संदर्भ चर की स्पष्ट परिभाषा के साथ टिप्पणियों की जगह लेते हैं (जो अप्रयुक्त होने पर अनुकूलित हो जाते हैं):

for(auto const &ent1 : mymap) {
  auto const &outer_key = ent1.first;
  auto const &inner_map = ent1.second;
  for(auto const &ent2 : inner_map) {
    auto const &inner_key   = ent2.first;
    auto const &inner_value = ent2.second;
  }
}

13
उत्तरों को प्रासंगिक बनाए रखने के लिए प्रॉप्स - मैं केवल यही चाहता हूं कि यह अपने तरीके को शीर्ष तक ले जाए। शायद इसे स्वीकार किए गए उत्तर में संपादित करना उचित होगा? (यह हम TeX.SX पर करते हैं, लेकिन SO एक अलग संस्कृति है।)
सीन एलायड

2
बस एक त्वरित प्रश्न, क्या आपके लेखन के निर्णय के constबाद कोई प्रासंगिकता है auto? क्या यह विशुद्ध रूप से सौंदर्यवादी है?
परम

6
एक प्रकार से पहले या बाद में @ तारम कांस्ट को वरीयता देना एक प्राथमिकता है, लेकिन मैं इसे सही रखने के लिए चुनता हूं क्योंकि यह उन स्थितियों में स्पष्ट करता है जहां पॉइंटर्स का उपयोग किया जा रहा है; उदाहरण के लिए जब दोनों का उपयोग कर रहे हैं int const *xऔर int *const xआप इसे लिख सकते हैं int const *const xजो कि आईएमओ की तुलना में बहुत स्पष्ट है const int *const x। लेकिन यह सिर्फ बाएं से दाएं पार्स है इसलिए प्रभाव समान है। इस सवाल के जवाब देखें: stackoverflow.com/questions/5503352/const-before-or-const-after
दंगा

2
ऑटो कॉन्स्टेंट & ent2 में & का क्या मतलब है?
टान्नर समर्स

5
@TannerSummers क्योंकि मूल्य तक पहुंच प्रत्येक तत्व की प्रतिलिपि बनाने की अक्षमता को जोड़ देगा; इसके अतिरिक्त यदि आप सामग्री को संशोधित करना चाहते हैं, तो आपको मूल्य के बजाय संदर्भ (या संकेत) द्वारा तत्वों तक पहुंचने की आवश्यकता होगी।
दंगा

308

आप एक पुनरावृत्त का उपयोग कर सकते हैं।

typedef std::map<std::string, std::map<std::string, std::string>>::iterator it_type;
for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
    // iterator->first = key
    // iterator->second = value
    // Repeat if you also want to iterate through the second map.
}

10
जब तक वह मानचित्र को संशोधित करने का इरादा नहीं करता, तब तक const_iterator का उपयोग करना बेहतर होगा।
माइकल आरोन सफायन

28
यह जब से यह एक अनावश्यक प्रतिलिपि से बचा जाता है जब यह iterator ++ की तुलना में ++ इटरेटर करने के लिए अधिक कुशल है।
Game_Overture

19
ऑटो का उपयोग करना C ++ 11 के लिए लूप को सरल करता है:for(auto iterator = m.begin(); iterator != m.end(); iterator++)
Gerard

127
यह c ++ 11 के लिए बहुत पुराना है। बस के लिए उपयोग करें (ऑटो iter: mymap)
अनाम

37
C ++ 11 के लिए, आपको संभावित प्रतिलिपि से बचने के लिए (ऑटो और iter: mymap) का उपयोग करना चाहिए।
देव_नट

60
for(std::map<std::string, std::map<std::string, std::string> >::iterator outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
    for(std::map<std::string, std::string>::iterator inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
        std::cout << inner_iter->second << std::endl;
    }
}

या C ++ 0x में अच्छे व्यक्ति:

for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
    for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
        std::cout << inner_iter->second << std::endl;
    }
}

2
आपको ऑटो & का उपयोग करना चाहिए, या यदि आप मानचित्र को संशोधित नहीं करते हैं, तो भी ऑटो और कास्ट करें। इसके अलावा, गैर-सदस्य प्रारंभ () और अंत () के लिए, (कास्ट ऑटो & iter = start (map); ...) को प्राथमिकता दें।
इला 782

13
या यहां तक ​​कि सरल: के लिए (कास्ट ऑटो और तत्व: नक्शा) cout << element.second;
इला

26

C ++ 17 (या बाद में) के साथ, आप "संरचित बाइंडिंग" सुविधा का उपयोग कर सकते हैं, जो आपको एक एकल टपल / जोड़ी का उपयोग करके, विभिन्न नामों के साथ कई चर को परिभाषित करने देता है। उदाहरण:

for (const auto& [name, description] : planet_descriptions) {
    std::cout << "Planet " << name << ":\n" << description << "\n\n";
}

मूल प्रस्ताव (दिग्गज Bjarne Stroustrup, हर्ब Sutter और गेब्रियल डॉस रीस द्वारा) को पढ़ने के लिए मजेदार है (और सुझाव वाक्य रचना अधिक सहज ज्ञान युक्त IMHO है); मानक के लिए प्रस्तावित शब्दांकन भी है जो पढ़ने के लिए उबाऊ है, लेकिन वास्तव में क्या होगा के करीब है।


2
यह बहुत सुंदर है मुझे C ++ 17 के बावजूद "वहां" नहीं होने के बावजूद वोट करने की आवश्यकता है। यार, वे साफ और सुरक्षित कोड लिखना आसान बनाकर C ++ को फिर से पुनर्जीवित कर रहे हैं।
जोनास

24

कुछ इस तरह से करें:

typedef std::map<std::string, std::string> InnerMap;
typedef std::map<std::string, InnerMap> OuterMap;

Outermap mm;

...//set the initial values

for (OuterMap::iterator i = mm.begin(); i != mm.end(); ++i) {
    InnerMap &im = i->second;
    for (InnerMap::iterator ii = im.begin(); ii != im.end(); ++ii) {
        std::cout << "map[" 
                  << i->first 
                  << "][" 
                  << ii->first 
                  << "] =" 
                  << ii->second 
                  << '\n';
    }
}   

दूसरे में इसके लिए ++ ii नहीं ++ i :) होना चाहिए
स्लिपस्ट्रीम

मुझे लगता है कि '/ n' अंत में एक '\ n' होना चाहिए
केनेकोर्न केटसोम्बुत

वैसे मैं उन्हें परिभाषित करने के लिए इस्तेमाल किया होगा बाद में उन्हें
दफनाने के

12

सी ++ 11:

std::map< std::string, std::map<std::string, std::string> > m;
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";

for (auto i : m)
    for (auto j : i.second)
        cout << i.first.c_str() << ":" << j.first.c_str() << ":" << j.second.c_str() << endl;

उत्पादन:

name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2

2
यह जवाब stackoverflow.com/a/27344958/3658660 से कैसे भिन्न है ? इस तथ्य को छोड़कर कि यह हर जगह प्रतियां बना रहा है।
hlscalon

1

std::map< std::string, std::map<std::string, std::string> >::const_iteratorमानचित्र का उपयोग करें


1
आप जानते हैं, कभी-कभी सही मार्जिन के पीछे कोड छिपाना एक अच्छी आदत नहीं है। मैं समझता हूं कि यह सुरक्षित है लेकिन अच्छी तरह से il कोड की दृष्टि को पूरी तरह से धुंधला कर देता है। जाओ autoभाई, या वह जो विम का उपयोग करता है वह कोओ जाएगा।
लुडोविक ज़ेनोएथ लैगौर्डेट

0

जैसा कि einpoklum ने अपने उत्तर में उल्लेख किया है , C ++ 17 के बाद से आप संरचित बाध्यकारी घोषणाओं का भी उपयोग कर सकते हैं । मैं मानचित्रों के नक्शे पर एक आरामदायक तरीके से पुनरावृत्ति के लिए पूर्ण समाधान प्रदान करके उस पर विस्तार करना चाहता हूं:

int main() {
    std::map<std::string, std::map<std::string, std::string>> m {
        {"name1", {{"value1", "data1"}, {"value2", "data2"}}},
        {"name2", {{"value1", "data1"}, {"value2", "data2"}}},
        {"name3", {{"value1", "data1"}, {"value2", "data2"}}}
    };

    for (const auto& [k1, v1] : m)
        for (const auto& [k2, v2] : v1)
            std::cout << "m[" << k1 << "][" << k2 << "]=" << v2 << std::endl;

    return 0;
}

नोट 1: नक्शा भरने के लिए, मैंने एक इनिशलाइज़र सूची का उपयोग किया (जो कि C ++ 11 है फीचर है)। यह कभी-कभी फिक्स्ड इनिशियलाइज़ेशन कॉम्पैक्ट रखने के लिए आसान हो सकता है।

नोट 2: यदि आप mछोरों के भीतर मानचित्र को संशोधित करना चाहते हैं , तो आपको हटाना होगाconst खोजशब्दों ।

कोलीरू पर कोड


0

पहला समाधान है, जैसे कि लूप के लिए रेंज रेंज का उपयोग करें:

नोट: जब range_expressionप्रकार है std::mapतो एक range_declarationप्रकार है std::pair

for ( range_declaration : range_expression )      
  //loop_statement

कोड 1:

typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;

StringToStringMap my_map;

for(const auto &pair1 : my_map) 
{
   // Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
   // pair1.first point to std::string (first key)
   // pair1.second point to std::map<std::string, std::string> (inner map)
   for(const auto &pair2 : pair1.second) 
   {
       // pair2.first is the second(inner) key
       // pair2.second is the value
   }
}

दूसरा समाधान:

कोड 2

typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;

StringToStringMap my_map;

for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
    // it1->first point to first key
    // it2->second point to inner map
    for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
     {
        // it2->second point to value
        // it2->first point to second(inner) key 
     }
 }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.