Jak mogę przeglądać mapę map w języku C++?

Jak mogę pętli przez std::map W C++? Moja mapa jest zdefiniowana jako:

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

Na przykład powyższy kontener przechowuje dane w następujący sposób:

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

Jak mogę przejrzeć tę mapę i uzyskać dostęp do różnych wartości?

Author: honk, 2011-01-30

9 answers

Stare pytanie, ale pozostałe odpowiedzi są nieaktualne od C++11 - możesz użyć w oparciu o pętlę i po prostu zrobić:

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

Powinno to być znacznie czystsze niż wcześniejsze wersje i uniknąć niepotrzebnych kopii.

Niektórzy zalecają zastąpienie komentarzy wyraźnymi definicjami zmiennych referencyjnych (które są optymalizowane, jeśli nie są używane):

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;
  }
}
 568
Author: Riot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 15:21:53

Możesz użyć iteratora.

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.
}
 309
Author: Puppy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-30 19:37:01
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;
    }
}

Lub ładniejszy w 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;
    }
}
 60
Author: Axel Gneiting,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-30 19:19:29

W C++17 (lub nowszym) możesz użyć funkcji "structured bindings", która pozwala zdefiniować wiele zmiennych o różnych nazwach, używając jednej krotki / pary. Przykład:

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

The original proposal (autorstwa luminarzy Bjarne Stroustrupa, Herba Suttera i Gabriela Dos Reisa) jest przyjemny w czytaniu (a sugerowana składnia jest bardziej intuicyjna IMHO); istnieje również proponowane sformułowanie standardu, które jest nudne do czytania, ale jest bliższe temu, co faktycznie wejdzie.

 27
Author: einpoklum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-18 18:43:08

Zrób coś takiego:

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';
    }
}   
 24
Author: Kevin Reid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-25 19:51:50

C++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;

Wyjście:

name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
 12
Author: user1438233,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-03 13:23:25

Użyj std::map< std::string, std::map<std::string, std::string> >::const_iterator, gdy mapa jest const.

 1
Author: Amir Saniyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 12:42:47

Jako einpoklum wymienione w ich ODPOWIEDŹ , od C++17 można również użyć strukturyzowanych deklaracji wiążących . W 2007 roku, po raz pierwszy w historii, w Polsce, w Polsce, w Polsce, w Europie, w Europie, w Europie, w Europie, na świecie, w Europie, na świecie, w Europie, na świecie, w Europie, na świecie, w Europie, na świecie.]}

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

Uwaga 1: do wypełnienia mapy użyłem listy inicjalizacyjnej (która jest C++11). Czasami może to być przydatne, aby zachować zwartość stałych inicjalizacji.

Uwaga 2: Jeśli jeśli chcesz zmodyfikować mapę m wewnątrz pętli, musisz usunąć const słowa kluczowe.

Kod na Coliru

 0
Author: honk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-01 15:32:47

Pierwszym rozwiązaniem jest użycie range_based dla pętli, jak:

Uwaga: Gdy typ range_expression jest std::map, to typ range_declaration jest std::pair.

for ( range_declaration : range_expression )      
  //loop_statement

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

Drugie Rozwiązanie:

Kod 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 
     }
 }
 0
Author: AmirSalar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-06 09:51:26