我试图在C ++中模仿R中的一些数据帧功能,即从CSV文件读取到矩阵并添加/删除行。 CSV文件中的行数可以是任何值,但列数及其数据类型是固定的。所以它不应该是太通用的(即列的可变数量的列或可变数据类型)。我已经能够创建一个基本程序,将数据读取到字符串向量的矢量。
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
using vec = vector<string>;
using matrix = vector<vec>;
matrix readCSV(string filename)
{
char separator = ',';
matrix result;
string row, item;
ifstream in(filename);
while(getline(in, row))
{
vec R;
stringstream ss(row);
while(getline(ss, item, separator)) R.push_back( item );
result.push_back(R);
}
in.close();
return result;
}
void printMatrix(const matrix &M)
{
for(vec row : M)
{
for (string s:row) cout << setw( 12 ) << left << s << " ";
cout << '\n';
}
}
void deleteRow(matrix &M, int row)
{
if(row < M.size()) M.erase( M.begin() + row );
}
void deleteCol(matrix &M, int col)
{
for(vec &row : M) if ( col < row.size() ) row.erase( row.begin() + col );
}
void edit( matrix &M, int i, int j, string value )
{
if (i < M.size() && j < M[i].size()) M[i][j] = value;
}
int main()
{
matrix pets = readCSV( "pets.csv" );
printMatrix( pets );
cout << "\n\n";
deleteRow( pets, 3 );
deleteCol( pets, 3 );
edit( pets, 1, 2, "12" );
printMatrix( pets );
}
pets.csv:
Animal,Name,Age,Food,Owner,Notes
Dog,Fido,6,Chewies,R. Smith,Barks
Cat,Fluffy,8,Whiskers,M. Jones,Miaows
Hamster,Giles,2,Scratchies,A. Green
Snake,Hissie,3,Mice,Bob
输出:
Animal Name Age Food Owner Notes
Dog Fido 6 Chewies R. Smith Barks
Cat Fluffy 8 Whiskers M. Jones Miaows
Hamster Giles 2 Scratchies A. Green
Snake Hissie 3 Mice Bob
Animal Name Age Owner Notes
Dog Fido 12 R. Smith Barks
Cat Fluffy 8 M. Jones Miaows
Snake Hissie 3 Bob
主要问题是所有列都具有相同的数据类型(在本例中为string)。我应该做哪些修改来允许不同数据类型的列(例如,在这种情况下,age列应该是int和其余的字符串)? 另外,如何在矩阵中添加新的行或列?
答案 0 :(得分:1)
如果每列都是不同的类型,则意味着您应该有一个对象向量,而不是向量向量。您没有处理表格数据,而是处理记录。
类似的东西:
struct Pet
{
std::string animal;
std::string name;
unsigned int age;
std::string food;
std::string owner;
std::string notes;
};
// Later
std::vector<Pet> pets;
在这个模型中:
如何在矩阵中添加新行?
将新的Pet
对象推入向量。
如何在矩阵中添加新列?
将新数据成员添加到Pet
类型。
如何将stringstream中的数据读入struct对象
使用辅助函数进行阅读:
Pet read_pet(std::string const &row)
{
Pet pet;
std::istringstream ss{row};
std::getline(ss, pet.animal, ',');
std::getline(ss, pet.name, ',');
ss >> pet.age;
ss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
std::getline(ss, pet.food, ',');
std::getline(ss, pet.owner, ',');
std::getline(ss, pet.notes, ',');
return pet;
}
然后将其推入矩阵?
while(getline(in, row))
{
result.emplace_back(read_pet(row));
}