2

I'm trying to read a file and store it's content into an unordered_map but I've got a little problem. This is my unordered_map:

std::unordered_map<std::string, std::vector<double>> _users;

And this is the content of the file that I'm trying to read:

Mike 4 NA 8 NA NA
Lena NA 8 4 NA 9

I want to store the content in _users in a way that the key is the name, and inside the vectors we have the numbers associated to the name. Moreover I want NA to be equal to 0. So I managed to do this:

while ( std::getline(file, line))
    {
        std::istringstream iss(line);
        std::string key;
        double value;
        iss >> key;
        dict[key] = std::vector<double>();

        while (iss >> value)
        {
            dict[key].push_back(value);
        }
    }

But since value is a double, when checking NA it just stops the while loop and I just get, for example with Mike: Mike 4. How can I do in order to get it to read NA and put it as 0 inside the vector ? Thank you for your help!

MM1
  • 912
  • 1
  • 10
  • 28
  • 3
    The shown code already demonstrates that you know everything that you need to know to do this. Instead of using `>>` to extract each word into a `double`, extract it into a `std::string`, check if it's "NA", otherwise construct a `std::istringstream`, and use `>>` with it to extract the `double` value. Mission accomplished. – Sam Varshavchik Jun 27 '20 at 22:04
  • Will this always be a row of 6 columns? – Tim Jun 27 '20 at 22:29

2 Answers2

2

For your inner loop, you could do:

    std::string stringval;
    while (iss >> stringval)
    {
        double value;
        try
        {
            value = std::stod (stringval);
        }
        catch (...)
        {
            value = 0.0;
        }
        dict[key].push_back(value);
    }
Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • 1
    Worth a quick mention that the downside with this approach is that any other garbage that appears in the input will be silently replaced with 0. – Tony Delroy Jun 30 '20 at 11:51
  • @TonyDelroy Yes, you could of course make it more sophisticated. I wanted to keep things simple. – Paul Sanders Jun 30 '20 at 14:48
0

I also tried something:

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

int main(int argc, char*[])
{
        //1. Read the file and load the map
        std::unordered_map<std::string, std::vector<double>> users{};

        std::ifstream file{"file.txt"};
        std::string line{};

        while(std::getline(file, line))
        {
                std::istringstream iss(line);
                std::string key{};
                iss >> key;

                std::vector<double> values{};

                while(iss)
                {
                        double value{0};
                        if (iss.str() != "NA")
                                iss >> value;
                        values.push_back(value);
                }

                users.insert({key, values});
        }

        //2. Printing the map
        for(auto const &[key, values]: users)
        {
                std::cout << "Key: " << key << std::endl;
                for(auto const value: values)
                {
                        std::cout << value << " ";
                }
                std::cout << std::endl;
        }

        return EXIT_SUCCESS;
}
Alexandre Gérault
  • 323
  • 1
  • 2
  • 13
  • 2
    Your code `if (iss.str() != "NA")` test is flawed, as you're not extracting a space-separated `std::string` token like "NA" to compare with: instead you're comparing with the whole `std::istringstream` content. – Tony Delroy Jun 30 '20 at 11:50