Как читать карту <string, vector <pair <int, string >>> - PullRequest
0 голосов
/ 13 мая 2018

У меня есть такая карта

typedef vector< pair<int, string> > Categories;  
map<string,Categories> cats;

, но когда я пытаюсь прочитать элементы карты, такие как

for(map<string,Categories>::const_iterator it = cats.begin(); it != cats.end(); ++it)
 {
    std::cout << it->first << " "  << it->second.first<<"\n";
 }

Я получаю ошибки

error: 'const class std::vector<std::pair<int, std::basic_string<char>
' has no member named 'first'  std::cout << it->first << " "  << it-> second.first<<"\n";

Ответы [ 4 ]

0 голосов
/ 18 июня 2018

Так как мы храним векторные категории внутри карты, нам придется итерировать вектор также:

 for(map<string,Categories>::const_iterator it = cats.begin(); it != cats.end(); ++it)
    {
        //iterator for vector (it->second)
        for(Categories::const_iterator it2 = it->second.begin(); it2 != it->second.end(); it2++ )
        {
              std::cout << it->first << " "  << it2->first<<" "<<it2->second <<"\n";
        }
    }
0 голосов
/ 13 мая 2018

Ошибка - это именно то, что сказал вам компилятор:

const class std::vector ' has no member named 'first'

Итак, вы должны решить, как напечатать карту, перегрузив ostreamartor, ниже пример того, как этого можно достичь:

#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>

typedef std::vector<std::pair<int, std::string>> Categories;  
std::map<std::string,Categories> cats;

std::ostream& operator << (std::ostream& os, const std::vector<std::pair<int, std::string>>& v) 
{
    os << "[";
    for (auto& el : v) {
        os << " " << el.first << " : " << el.second;
    }
    os << "]";
    return os;
}

int main() {
    cats.emplace("cat1", std::vector<std::pair<int, std::string>>(1, std::make_pair(1, "category1")));
    for(auto& cat : cats) {
        std::cout << cat.first << " "  << cat.second << "\n";
    }
}
0 голосов
/ 14 мая 2018

ошибка : в классе const std :: vector нет члена с именем first std :: cout << it-> first << "" << it-> second.first << "\ n"; </p>

Это ясно, как Кристалл, что у вас может быть много элементов в ваших value с вашей карты, которая является std::vector< std::pair<int, std::string>>

Тогда как бы вы распечатали элементы вектора? Варианты:

  1. произвольный доступ (т. Е. vec[index])
  2. итератор (т. Е. std::vector< std::pair<int, std::string>>::const_iterator itr;)
  3. или по диапазону на основе цикла (т. Е. for(const auto& it: vec))

В вашем случае, если вы хотите что-то простое и удобное, используйте цикл на основе диапазона:

   for(const auto& it: cats)
   {
      std::cout << it.first << " = "; // keys
      for(const auto& ve: it.second)  // values vec
         std::cout << ve.first << "-" << ve.second << "\t";
      std::cout << std::endl;
   }

Если вы все еще хотите иметь длинные iterator петли, вот оно.

см. Прямую трансляцию здесь: https://www.ideone.com/3bS1kR

#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <iterator>

typedef std::vector< std::pair<int, std::string>> Categories;

int main()
{
   std::map<std::string, Categories> cats;

   cats["key1"] = {std::make_pair(1, "pair1"), std::make_pair(1, "pair2"), std::make_pair(1, "par3")};
   cats["key2"] = {std::make_pair(2, "pair1"), std::make_pair(2, "pair2")};
   cats["key3"] = {std::make_pair(3, "pair1")};

   std::cout << "Range based loop \n";
   for(const auto& it: cats)
   {
      std::cout << it.first << " = ";  // keys
      for(const auto& ve: it.second)   // values vec
         std::cout << ve.first << "-" << ve.second << "\t";
      std::cout << std::endl;
   }

   std::cout << "\nIterator loop \n";
   std::map<std::string, Categories>::const_iterator it;
   std::vector< std::pair<int, std::string>>::const_iterator curr_val_it;
   for(it = cats.cbegin(); it != cats.cend(); ++it)
   {
      std::cout << it->first << " = "; // keys

      for(curr_val_it = it->second.cbegin(); curr_val_it != it->second.cend(); ++curr_val_it )
          std::cout << curr_val_it->first << "-" << curr_val_it->second << "\t";  // values vec

      std::cout << std::endl;
   }


   return 0;
}
0 голосов
/ 13 мая 2018

сначала вам нужно получить доступ к элементу вектора, а затем к паре внутри.

... it->second[0].first<< ...

лучшее значение цикла:

for(const auto& cat : cats)
 {
     string mapidx = cat.first;
     vector<pair<int, std::string>> catvect = cat.second;
 }

тогда у вас может быть отдельный цикл для чтения содержимого вектора:

for(const auto& cat : cats)
 {
     string mapidx = cat.first;
     vector<pair<int, std::string>> catvect = cat.second;
     for (const auto& entry : catvect)
     {
         int number = entry.first;
         string whatever = entry.second;
     }
 }

временные переменные предназначены только для удобства чтения, нет необходимости во всех копиях;)

...