Home > Software engineering >  How to extract one row of a 2D string vector to vector of double?
How to extract one row of a 2D string vector to vector of double?

Time:09-25

I have a function to calculate moving average:

void MovingAverage(double inputSeries[]
                 , size_t inputSize, size_t window, float* output ) 

My train of thought to do my calculation:

  1. construct a loop and extract one row of vec2D each time
  2. use the MovingAverage function to get output

For the first step, the 2d-vector is parsed from a csv file:

std::vector<std::vector<std::string>> vec2D{
    {"S0001","01","02","03"}, {"S0002","11","12","13"}, {"S0003","21","22","23"}
};

I want to extract one row of this 2D vector (say the 2nd) and store the row as a 1d vector std::vector<double> copyRow then calculate the moving average for each row.

copyRow = {11,12,13}

I tried vector<double> copyRow(vec2D[0].begin(), vec2D[0].end()); but it doesn't work because the 2D vector is std::string type.

I also tried for loops:

int rowN = vec2D.size();
int colN = vec2D[0].size();
double num;
for (int i = 0; i < rowN; i  ) 
{
    for (int j = 0; j < colN; j  ) 
    {
        num = stod(vec2D[i][j]);
        copyRow[i][j].push_back(num);
    }
}

But it appends all values from all rows into the vector. What would be the best way to do this?

CodePudding user response:

I tried vector<double> copyRow(vec2D[0].begin(), vec2D[0].end()); but it doesn't work because the 2D vector is string type.

You can make use of the algorithm function std::transform from <algorithm> to do this.

Since the first element of each row cannot be transformed to a double , you can skip it by starting from one element after begin iterator:

 #include <algorithm> // std::transform

std::vector<double> copyRow;
// reserve memory for unwanted real locations
copyRow.reserve(vec2D[1].size() - 1u);

std::transform(std::cbegin(vec2D[1])   1, std::cend(vec2D[1])
    , std::back_inserter(copyRow), [](const auto& ele) {
        return std::stod(ele);
    });

(See a Demo)

CodePudding user response:

After the comments in the main thread, it seems that the initial data structure (a 2D vector of strings), doesn't seem to be the best choice.

Instead, an associative container, such as a std::map or std::unordered_map would seem to be more suited for the task you're trying to accomplish. Basically, the key to the map is the non-numeric field, and the data would be the vector<double> associated with the key.

Then it just becomes a matter of getting a reference to the row of doubles, given the key value.

Here is an example of code that illustrates this:

#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

std::string test = "S0001,01,02,03,S0002,11,12,13,S0003,21,22,23";

int main()
{
  std::map<std::string, std::vector<double>> mymap;
  int numCols = 4;
  int count = 0;

  std::istringstream strm(test);
  std::string data;
  std::string id;
  
  while(std::getline(strm, data, ','))
  {
      if ( count % numCols == 0)
          id = data;
      else              
         mymap[id].push_back(stod(data));
       count;
  }
  
  for (auto& m : mymap)
  {
      std::cout << "\n" <<  m.first << "\n";
      for (auto& v : m.second)
         std::cout << "  " << v << "\n";
  }
  
  // Get the vector associated with S0002
  std::cout << "\nHere is the data for S0002:" << "\n";
  std::vector<double>& vDouble = mymap["S0002"];
  for (auto& d : vDouble)
     std::cout << d << " ";
}

Output:

S0001
  1
  2
  3

S0002
  11
  12
  13

S0003
  21
  22
  23

Here is the data for S0002:
11 12 13 

There are two main points:

  1. The vector of strings no longer becomes an issue, since on the population of the std::vector<double> elements, the std::stod is called on the string to convert the string to a double.

  2. Accessing the std::vector<double> becomes trivial -- all you need to do is get the key (the string data) and access (by reference in this example), the vector associated with the key. No copying, no std::transform calls, or anything like that.

  • Related