поэтому я пытаюсь выяснить, как сортировать файлы CSV, чтобы помочь организовать данные, которые мне нужны для экономической статьи. Файлы массивны и их много (около 587 мб файлов на молнии). Файлы организованы по столбцам, в которых все имена переменных находятся в первой строке, и все данные для этой переменной находятся под ней. Моя цель состоит в том, чтобы иметь возможность брать столбцы, начинающиеся с указанной строки (ex input: "MC1", Get: MC10RT2, MC1WE02,...), а затем сохранять их в отдельный файл. Кто-нибудь имеет какие-либо рекомендации относительно того, какую форму должен принимать код?
Просто для удовольствия небольшая программа, которая должна работать на вас. Вещь, в которую вы будете boost::split(columns, str, boost::is_any_of(","), boost::token_compress_off);
- boost::split(columns, str, boost::is_any_of(","), boost::token_compress_off);
что здесь создайте vector
string
из string
csv-стиля.
Очень простой пример, но ваш вопрос был предлогом немного поиграть с алгоритмами boost string, которые я знал, но никогда не использовал...
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <set>
// Typedefs for eye candy
typedef std::vector<std::string> Fields;
typedef std::vector<Fields> Results;
typedef std::set<unsigned long> Columns;
// Split the CSV string to a vector of string
Fields split_to_fields(const std::string& str)
{
Fields columns;
boost::split(columns, str, boost::is_any_of(","),
boost::token_compress_off);
return columns;
}
// Read all the wanted columns
Results read_columns_of_csv(std::istream& stream, const Columns& wanted_columns)
{
std::string str;
Results results;
while (getline(stream, str))
{
Fields line{split_to_fields(str)};
Fields fields;
for (unsigned long wanted_column: wanted_columns)
{
if (line.size() < wanted_column)
{
std::cerr << "Line " << (results.size() + 1 )
<< " does not contain enough fields: "
<< line.size() << " < " << wanted_column
<< std::endl;
}
else
{
fields.push_back(line[wanted_column]);
}
}
results.push_back(fields);
}
return results;
}
// Read the ids of the columns you want to get
Columns read_wanted_columns(unsigned long max_id)
{
Columns wanted_columns;
unsigned long column;
do
{
std::cin >> column;
if ((column < max_id)
&& (column > 0))
{
wanted_columns.insert(column - 1);
}
}
while (column > 0);
return wanted_columns;
}
// Whole read process (header + columns)
Results read_csv(std::istream& stream)
{
std::string str;
if (!getline(stream, str))
{
std::cerr << "Empty file !" << std::endl;
return Results{};
}
// Get the column name
Fields columns{split_to_fields(str)};
// Output the column with id
unsigned long column_id = 1;
std::cout
<< "Select one of the column by entering its id (enter 0 to end): "
<< std::endl;
for (const std::string elem: columns)
{
std::cout << column_id++ << ": " << elem << std::endl;
};
// Read the choosen cols
return read_columns_of_csv(stream, read_wanted_columns(column_id));
}
int main(int argc, char* argv[])
{
// Manage errors for filename
if (argc < 2)
{
std::cerr << "Please specify a filename" << std::endl;
return -1;
}
std::ifstream file(argv[1]);
if (!file)
{
std::cerr << "Invalid filename: " << argv[1] << std::endl;
return -2;
}
// Process
Results results{read_csv(file)};
// Output
unsigned long line = 1;
std::cout << "Results: " << results.size() << " lines" << std::endl;
for (Fields fields: results)
{
std::cout << line++ << ": ";
std::copy(fields.begin(), fields.end(),
std::ostream_iterator<std::string>(std::cout, ","));
std::cout << std::endl;
}
return 0;
}
Я предлагаю использовать вектор структур.
Структура позволит каждой строке иметь другой тип.
Ваша программа будет иметь следующую структуру: