【发布时间】:2012-05-01 20:29:16
【问题描述】:
我的数据如下所示:
token eps rank # first line names columns
Intercept 9.362637e+00 1 # later lines hold data
A1 -2.395553e-01 30
G1 -3.864725e-01 50
T1 1.565497e-01 43
....
不同的文件将具有不同数量的命名列,并且每列中的值类型会因浮点数、整数和字符串而异。
我想编写一个readCols 函数,向它发送列的名称(例如,我可能需要token 和rank 列),它将把指定列中的数据放入适当类型的容器中.
我的问题不在于解析文件,而在于返回包含不同类型的可变数量的容器。例如,我希望将token 和rank 列分别放入vector<string> 和vector<int> 容器中。这里的问题是我可能想要eps 列(存储在向量中),并且我不想为每种可能的类型组合编写不同的readCols 函数。 (容器的类型对我来说无关紧要。如果我必须只使用vectors,没问题;每个容器包含不同的类型是关键。)
我可能需要一个容纳不同类型的容器来容纳不同类型的容器。看起来Boost.Variant 可能是我想要的解决方案,但我不知道如何告诉解析器我希望每列是哪种类型(我可以制作一个类型名列表之类的东西吗?例如void readCols(string filename, vector<variant<various types of vector>> &data, vector<string> colNames, vector<typename> convertTo))。同样,Boost.Mpl.Vector 可能会解决问题,但我还是不知道如何告诉readCols 每列要如何转换。
我能想到至少两种解决方法:
- 使用读入任何容器的模板函数分别读取每一列(
container::value_type允许函数知道如何解析)。我不喜欢这种解决方案,因为文件有时很大(数百万行),因此多次解析它们会花费额外的几分钟(在计算大约需要 30 分钟的程序中,运行时间的百分比可忽略不计;程序将一遍又一遍地跑)。 - 将所有列读入字符串容器并在调用上下文而不是解析上下文中重新转换它们。这不会那么糟糕,因为我认为我可以使用
std::transform和boost::lexical_cast或 s/t 在一行中进行转换。如果我可以避免2n的膨胀行,那就太好了(n= 列数,通常为 2 或 3,每列 2 行来声明容器然后转换)。
与完整的通用解决方案相比,第二种解决方法可能需要我付出的努力要少得多;如果是这样的话,我想知道。我想第二种解决方法甚至可能更有效,但我目前主要关心的是易用性。如果我可以编写一个通用的readCols 函数并完成它,那就是我更喜欢的。
【问题讨论】:
-
@jrok 我从来没有,但应该可以。
标签: c++ boost generic-programming boost-mpl boost-variant