user3325937
user3325937

Reputation: 13

implementing an unordered map within an unordered map

I am reading data from a file and trying to set it up as an unordered map within another unordered map so that I can have 2 keys for a certain value. The file contains vertices and the distance from one to the other. I am using this code to read from the file and create the ordered maps but it doesn't work. I looked for examples on how to implement the unordered maps but I didn't find anything online.

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <vector>
#include <unordered_map>
#include <set>


int main()
{
    std::unordered_map<std::string,std::unordered_map<std::string,int>> left_vertex;
    std::set<std::string> vertices;
    int i=0,j=0,distance = 0;
    std::string start_vertex = "",outer_key = " ",inner_key = " ";
    std::unordered_map<std::string,std::unordered_map<std::string,int>>::iterator it;
    std::set<std::string>::iterator it2;

    for(std::string line;std::getline(std::cin,line);)
    {
        std::stringstream line_stream(line);

        for(std::string token;std::getline(line_stream,token,' ');)
        {
            if(i==0)
            {
                start_vertex = token;
                break;
            }

            if(j==0)
            {
                outer_key = token;
                vertices.insert(outer_key);
            }

            if(j==1)
            {
                inner_key = token;
            }
            if(j==2)
            {
                distance = std::stoi(token);
            }
            j++;

        }

        for(it2 = vertices.begin();it2!=vertices.end();it2++)
        {
            if(*it2 == outer_key)
            {
                //left_vertex.insert(std::make_pair(outer_key,std::make_pair(inner_key,distance)));
                left_vertex[outer_key][inner_key]=distance;
            }
            else
            {
                left_vertex[outer_key] = std::make_pair(inner_key,distance);
            }
        }
        outer_key = " ";
        inner_key = " ";
        distance = 0;
        j=0;
        i++;

    }

    for(it = left_vertex.begin(); it != left_vertex.end();it++)
    {
        std::cout<<it->first<<std::endl;
    }

    return 0;
}

the file that I am reading from looks like this.

A 
A B 1
A C 5
B C 2
B D 4
C D 1
C E 4
D E 2

the first line is the starting vertex. after that the 3 element in each line represents the distance from the first element to the second element in each line.

Upvotes: 1

Views: 2583

Answers (2)

Zilicon
Zilicon

Reputation: 3860

I encountered two problems in your code:

  • The line with std::make_pair just didn't compile.
  • Your print strategy was wrong for this kind of sophisticated double-map.

Other than that your code did pretty much what you wanted it to do.
I took the liberty of reformatting it and making it a little shorter and simpler - you had a couple of unnecessary for loops.

#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>

int main()
{
    std::unordered_map<std::string, std::unordered_map<std::string, int>> doubleMap;
    std::unordered_map<std::string, std::unordered_map<std::string, int>>::iterator it;
    std::unordered_map<std::string, int>::iterator it2;
    std::string key1, key2, distanceStr;

    std::string line;
    std::getline(std::cin, line); // Read the unwanted line
    while (std::getline(std::cin, line)) {
        std::stringstream line_stream(line);
        std::getline(line_stream, key1, ' ');
        std::getline(line_stream, key2, ' ');
        std::getline(line_stream, distanceStr, ' ');

        doubleMap[key1][key2] = std::stoi(distanceStr);
    }

    for (it = doubleMap.begin(); it != doubleMap.end(); ++it) {
        std::cout << it->first << std::endl;
        for (it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
            std::cout << "  " << it2->first << " " << it2->second << std::endl;
        }
    }

    return 0;
}

The output of this code when I input your file is this:

A
  C 5
  B 1
D
  E 2
C
  D 1
  E 4
B
  D 4
  C 2

Upvotes: 1

Christophe
Christophe

Reputation: 73376

Your datastructure with a double unordered_map is intersting. However the code you use looks a little bit too complex.

Just replace your for(it2 ...) loop block with the following:

    if (i!=0)   // for the first line the data is irrelevant
        left_vertex[outer_key][inner_key] = distance;  // just insert !  

Adding the following output code at the end:

for (it = left_vertex.begin(); it != left_vertex.end(); it++) {
    std::cout << it->first << std::endl<<"\t";
    for (auto x : it->second)
        std::cout << x.first << x.second<<" ";
    cout << endl; 
}

Permits to sse the result:

A
        B1 C5
B
        C2 D4
C
        D1 E4
D
        E2

Some other suggestions:

For your reading of line_stream, you could as well write somethin like line_stream>>outer_key>>inner_key>>distance; which would make counter j and intermediary token useless.

You could also check at the end, if vertices is consistent with the inner_keys, as this is currently not ensured.

Upvotes: 0

Related Questions