次のようなデータがあります。
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
....
ファイルが異なれば名前付き列の数も異なり、各列の値の型は float、int、および string の間で異なります。
指定された列のデータを適切なタイプのコンテナーに入れる列readCols
の名前を送信する関数を作成したいと考えています (たとえば、列token
と列が必要な場合があります)。rank
私の問題は、ファイルの解析ではなく、さまざまなタイプを含む可変数のコンテナーを返すことです。たとえば、token
および列をおよびコンテナーにそれぞれrank
入れたいとします。ここでの問題は、代わりに (ベクトルに格納された) 列が必要になる可能性があり、考えられるすべての型の組み合わせに対して異なる関数を記述したくないということです。(コンテナのタイプは私には関係ありません。s のみを使用する必要がある場合は問題ありません。各コンテナに異なるタイプが含まれていることが重要です。)vector<string>
vector<int>
eps
readCols
vector
おそらく、さまざまな種類のコンテナーを保持するために、さまざまな型を保持するコンテナーが必要になるでしょう。Boost.Variantが私が望む解決策のように見えますが、パーサーに各列をどの型にするかを伝える方法がわかりません (型名のリストのようなものを作成できますか? などvoid readCols(string filename, vector<variant<various types of vector>> &data, vector<string> colNames, vector<typename> convertTo)
)。同様に、Boost.Mpl.Vectorは問題を解決するかもしれませんが、ここでも、readCols
各列がどのようにキャストされるかを知る方法がよくわかりません。
少なくとも 2 つの回避策が考えられます。
- 任意のコンテナーに読み込むテンプレート化された関数を使用して、各列を個別に読み取ります (
container::value_type
関数が解析方法を認識できるようにします)。私はこの解決策を好みません。なぜなら、ファイルが時々大きくなる (数百万行) ため、ファイルを複数回解析すると余分に数分かかるからです (計算に 30 分ほどかかるプログラムでは、実行時間の無視できる割合ではありません。プログラムは何度も走ります)。 - すべての列を文字列のコンテナーに読み取り、解析コンテキストではなく呼び出しコンテキストで再キャストします。
std::transform
andboost::lexical_cast
または s/tを使用して 1 行で変換できると思うので、これはそれほど悪くはありません。2n
行の肥大化を避けることができれば、すばらしい (n
= 列の数、通常は 2 または 3、コンテナーを宣言してから変換するための列ごとに 2 行)。
2 番目の回避策は、完全で一般的な解決策よりもはるかに少ない労力で済む可能性があります。もしそうなら、私は知りたいです。2 番目の回避策の方が効率的かもしれないと想像しますが、現時点では主に使いやすさに関心があります。ジェネリックreadCols
関数を 1 つ記述してそれで完了できるなら、それが私の好みです。