-1

What is a good way to convert vector<string> line to vector<vector <double> > d?

I have 500x9 vector string data reading from a file,

vector<string> line;

I need to convert this string vector into 2D vector array of size (500 rows, 9 columns)

vector<vector <double> > d;

Code:

using namespace std;

int main()
{

    /// read file data ///
    std::ifstream myfile;
    myfile.open("somefile.txt");
    std::vector<string> lines;
    std::string str;
    while(getline(myfile,str))
        lines.push_back(str);
    myfile.close();

    std::vector< std::vector<double> > data;
    /// convert string to double ///
    std::transform(lines.begin(), lines.end(), data.begin(), std::stod);

}
Barmar
  • 741,623
  • 53
  • 500
  • 612
ash
  • 13
  • 3
  • 2
    Here's a suggestion: open an editor, and write some code. – Sam Varshavchik Jun 23 '16 at 01:51
  • Possible duplicate of [How can I read and parse CSV files in C++?](http://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c) – Barmar Jun 23 '16 at 02:15
  • @Barmar .. thanks for help with editing ..., no, its way different, I am already able to read data from .txt file not csv, my main problem is to convert string vector into 2d - vector of doubles .. later I will have to extract individual columns – ash Jun 23 '16 at 02:22
  • How is that different? You have a comma-separated list of numbers, and the CSV reader will return a 2d vector. – Barmar Jun 23 '16 at 02:23
  • 1
    well 1st it is not comma-separated .. its just spaces and I think it can be solved in one or two lines of code .. instead of creating new class like in that question I have problem with this line of code.. and this should transform strings into double. ..correct me if I am wrong ? std::transform(lines.begin(), lines.end(), data.begin(), std::stod); thanks for your help – ash Jun 23 '16 at 02:28
  • @Barmar I'd also argue that parsing data in a `vector` is far different from reading Comma Separated Values from a stream. ([Though using a `sregex_token_iterator` may help them feel similar](http://stackoverflow.com/a/28880605/2642059).) – Jonathan Mee Jun 23 '16 at 03:06

1 Answers1

1

I'm about as big a fan of standard algorithms as you can find. But I believe your best case here is a good old fashion while-loop (this is particularly true if you're not sure that line is divisible by 9: Using an iterator to Divide an Array into Parts with Unequal Size)

vector<vector<double>> d(line.size() / 9, vector<double>(9));

for(auto i = 0U; i + 9 <= line.size(); i += 9) {
    transform(next(cbegin(line), i), next(begin(line), i + 9), begin(d[i / 9]), [](const auto& it){return stod(it);});
}

Live Example

Note the call to stod is wrapped in a lambda.

  • transform(cbegin(lines), cend(lines), begin(d[i / 9]), stod) won't work because the compiler doesn't know whether you're calling double stod(const string&, size_t*) or double stod(const wstring&, size_t*)
  • transform(cbegin(lines), cend(lines), begin(d[i / 9]), static_cast<double (*)(const string&, size_t*)>(stod)) won't work because the defaulted second argument is not preserved by the function pointer
  • transform(cbegin(lines), cend(lines), begin(d[i / 9]), bind(static_cast<double (*)(const string&, size_t*)>(stod), placeholders::_1, 0)) does work equivalently to the lambda
Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Thanks Jonathan.. much appreciated your time and effort .. this method works well though I managed to do it another way as well :) – ash Jun 23 '16 at 08:32
  • Incidentally, cause I didn't do this in my example, you can print `d` using: `for(const auto& i : d) copy(cbegin(i), cend(i), ostream_iterator(cout, "\t"));` – Jonathan Mee Jun 23 '16 at 10:41