【问题标题】:How to extract one row of a 2D string vector to vector of double?如何将一行二维字符串向量提取为双精度向量?
【发布时间】:2021-11-18 00:12:48
【问题描述】:

我有一个计算移动平均线的函数:

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

我的计算思路:

  1. 构造一个循环,每次提取一行vec2D
  2. 使用MovingAverage函数获取输出

第一步,从 csv 文件中解析二维向量:

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

我想提取这个二维向量的一行(比如第二个)并将该行存储为一维向量std::vector&lt;double&gt; copyRow,然后计算每一行的移动平均值。

copyRow = {11,12,13}

我尝试了vector&lt;double&gt; copyRow(vec2D[0].begin(), vec2D[0].end());,但它不起作用,因为二维向量是std::string 类型。

我也试过 for 循环:

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);
    }
}

但是它将所有行中的所有值附加到向量中。最好的方法是什么?

【问题讨论】:

  • 而且由于行数太多,每一行我都必须进行计算,我不想只使用一个循环并指定行索引来这样做
  • 我编辑了我的问题,谢谢@JaMiT
  • 我想提取这个二维向量的一行(比如第二个)并将该行存储为一维向量——听起来你正在给我们你的解决方案,并且试图让您的解决方案发挥作用。也许在高层次上描述一下,你想解决什么问题?也许有更好的方法来实现您想要实现的任何目标。
  • @Cyan "对于每一行我必须进行计算," -- 这似乎是将您的 2D string 数据转换为 2D double 的原因数据,而不是提取单行数据。这让我认为,也许您应该提供更多背景信息,以便我们更好地了解您所面临的限制(并更好地了解您的目标,正如 PaulMcKenzie 建议的那样)。
  • @JaMiT 是的,实际上我想计算每一行的移动平均值。我编辑了我的问题

标签: c++ algorithm c++11 stdvector stdstring


【解决方案1】:

我试过vector&lt;double&gt; copyRow(vec2D[0].begin(), vec2D[0].end());,但它不起作用,因为二维向量是字符串类型。

你可以利用&lt;algorithm&gt;中的算法函数std::transform来做到这一点。

由于每行的第一个元素无法转换为 double ,因此您可以在 begin 迭代器之后从一个元素开始跳过它:

 #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)

【讨论】:

  • 谢谢,但您可以从我编辑的问题中看到,每行的第一个元素不能转换为浮点数
  • 谢谢,它似乎有效,但在我的代码中它显示 auto' not allowed in lambda parameter 我该如何解决这个问题?
  • @Cyan Generic lambda(如本答案所示)需要 c++14 或更高版本。你的可能仍然是 c++11。尝试 [](const std:: string& ele) { return std::stod(ele); });作为 lambda。
【解决方案2】:

在主线程中的 cmets 之后,似乎初始数据结构(字符串的 2D 向量)似乎不是最佳选择。

相反,std::mapstd::unordered_map 等关联容器似乎更适合您要完成的任务。基本上,映射的键是非数字字段,数据是与键关联的vector&lt;double&gt;

那么只要给定键值,就可以获取对双精度行的引用。

下面是一个说明这一点的代码示例:

#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 << " ";
}

输出:

S0001
  1
  2
  3

S0002
  11
  12
  13

S0003
  21
  22
  23

Here is the data for S0002:
11 12 13 

主要有两点:

  1. 字符串向量不再成为问题,因为在填充std::vector&lt;double&gt; 元素时,在字符串上调用std::stod 以将字符串转换为双精度。

  2. 访问std::vector&lt;double&gt; 变得微不足道——您需要做的就是获取密钥(字符串数据)并访问(在此示例中通过引用)与密钥关联的向量。没有复制,没有std::transform 电话,或类似的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    相关资源
    最近更新 更多