2017-09-21 14 views
0

C言語でRからデータフレーム機能の一部を模倣しようとしています。つまり、CSVファイルから行列を読み込んで行を追加/削除します。 CSVファイルの行数は任意ですが、列数とデータ型は固定されています。したがって、あまりにも汎用的ではない(つまり、列の可変数または列の可変データ型)ことは想定されていません。私は文字列ベクトルのベクトルにデータを読み込む基本的なプログラムを作ることができました。C++:ベクトルのベクトルに行を追加する

#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 

主な問題は、すべての列が同じデータ型(この場合は、文字列)であることです。異なるデータ型の列を許可するためにはどのような変更を行う必要がありますか?(この場合、年齢列はint型と残りの文字列型にする必要があります) また、行列に新しい行や列を追加するにはどうすればよいですか?

答えて

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タイプに新しいデータメンバーを追加します。

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

、その後、行列にそれをプッシュする:私は読書を行うためにヘルパー関数を使用しStructオブジェクト

ににstringstreamからデータを読み取ることができますどのように

while(getline(in, row)) 
{ 
    result.emplace_back(read_pet(row)); 
} 
+0

彼は汎用CSVコードではなく、事前に定義されたレコードタイプで動作する何かを書いているように見えます。 – Barmar

+2

@Barmarそれは明らかではない。それが目標であれば、「異なるデータ型の列を許可するためには何を修正すべきですか?(この場合、年齢列はintと残りの文字列でなければなりません)?」*は絶対に意味をなしません。 CSVの文字列。だから答えが私の答えか、答えは "あなたはCSVデータが入力されていないためではありません。" – cdhowie

+0

それでは "vec"は "Pet"に置き換えられます。私はもはやwhile(getline(ss、item、separator))を使って、以前のようにファイルから行を読み込むことができなくなると思っています。 R.push_back(item); – u23

関連する問題