从零开始的CPP(36)——操作Excel

ops/2024/9/24 21:35:47/

现有一个Excel A1.csv。

其表格第一列为:生物样本的名称;其他列为:生物样本的含量。表格第一行第一列是空格,第一行其他列为:受试者名称。

需求

如下:设计一个程序,可以指定受试者名称(某列),对该列所有生物样本含量进行排序,保留含量前X名的生物样本,其余生物样本含量合并,命名为others。

设计思路:

1.如何根据受试者名称(第一行),读取csv中指定某列数据?

vector<string> getRownames() {ifstream file("A1.csv");string line;string rowname;vector<string> rownames;getline(file, line);for (int i = 0; i < line.length();) {if (line[i] == ',') {rowname = line.substr(0, i);rownames.push_back(rowname);line = line.substr(i + 1, line.length());i = 0;}else i++;}for (auto i : rownames) {cout << i << " ";}return rownames;
}

通过这段代码,就可以得到一个储存每列名称的vector了。

int findRowname(vector<string> rownames,string aim) {for (int i = 0; i < rownames.size(); i++) {if (rownames[i] == aim) {return i;}}
}

 通过这段代码,就可以得到目标受试者所在列了。

2.如何获得目标受试者所在列的数据及其对应样本名称?

vector<pair<string, double>> getNameAndData(int row) {vector<pair<string, double>> NameAndData;ifstream file("A1.csv");string line;string rowdata;double value;getline(file, line);while (getline(file, line)) {vector<string> rowdatas;for (int i = 0; i < line.length();) {if (line[i] == ',') {rowdata = line.substr(0, i);rowdatas.push_back(rowdata);line = line.substr(i + 1, line.length());i = 0;}else i++;}            value = stod(rowdatas[row]);NameAndData.push_back({ rowdatas[0], value });}for (auto i : NameAndData) {cout << i.first << " " << i.second << endl;}return NameAndData;
}

循环读取文件每一行,把每一行都存进vector,找到vector的0列(样本名)与row列(受试者所在列),将其pair,存入新vector。

这里有代码重复了,就是从line转换为vector的代码,可以将其封装。

void split(string line, vector<string>& linedatas) {string linedata;for (int i = 0; i < line.length();) {if (line[i] == ',') {linedata = line.substr(0, i);linedatas.push_back(linedata);line = line.substr(i + 1, line.length());i = 0;}else i++;}return;
}

需要时直接传入line和vector就可以啦。

3. 排序,并保留前X行,剩余行合并为others

复习了lambda表达式与sort函数结合的用法

vector<pair<string, double>> getNewNameAndData(vector<pair<string, double>> NameAndData,int reserve) {sort(NameAndData.begin(), NameAndData.end(), [](const auto& a, const auto& b) {return a.second > b.second;});vector<pair<string, double>> NewNameAndData(reserve + 1);for (int i = 0; i < reserve; i++) {NewNameAndData[i] = NameAndData[i];}double reservesum = 0;for (int i = reserve; i < NameAndData.size(); i++) {reservesum = reservesum + NameAndData[i].second;}NewNameAndData[reserve] = { "Others",reservesum };for (auto i : NewNameAndData) {cout << i.first << " " << i.second << endl;}return NewNameAndData;
}

 4.将new vector写入新文件

void getNewCsv(vector<pair<string, double>> NewNameAndData,int row) {ofstream file("newA.csv");ifstream file1("A1.csv");string line;getline(file1, line);vector<string> data0;split(line, data0);file << data0[0] << "," << data0[row] << endl;for (int i = 0; i < NewNameAndData.size(); i++) {file << NewNameAndData[i].first << "," << NewNameAndData[i].second << endl;}return;
}

5.完整代码

#include <iostream>
#include <fstream>
#include <sstream>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;
class Solution {
public:vector<string> getRownames() {ifstream file("A1.csv");string line;string rowname;vector<string> rownames;getline(file, line);split(line, rownames);/*for (auto i : rownames) {cout << i << " ";}*/return rownames;}int findRowname(vector<string> rownames,string aim) {for (int i = 0; i < rownames.size(); i++) {if (rownames[i] == aim) {return i;}}return 0;}vector<pair<string, double>> getNameAndData(int row) {vector<pair<string, double>> NameAndData;ifstream file("A1.csv");string line;string rowdata;double value;getline(file, line);while (getline(file, line)) {vector<string> rowdatas;split(line, rowdatas);value = stod(rowdatas[row]);NameAndData.push_back({ rowdatas[0], value });}/*for (auto i : NameAndData) {cout << i.first << " " << i.second << endl;}*/return NameAndData;}vector<pair<string, double>> getNewNameAndData(vector<pair<string, double>> NameAndData,int reserve) {sort(NameAndData.begin(), NameAndData.end(), [](const auto& a, const auto& b) {return a.second > b.second;});vector<pair<string, double>> NewNameAndData(reserve + 1);for (int i = 0; i < reserve; i++) {NewNameAndData[i] = NameAndData[i];}double reservesum = 0;for (int i = reserve; i < NameAndData.size(); i++) {reservesum = reservesum + NameAndData[i].second;}NewNameAndData[reserve] = { "Others",reservesum };/*for (auto i : NewNameAndData) {cout << i.first << " " << i.second << endl;}*/return NewNameAndData;}void getNewCsv(vector<pair<string, double>> NewNameAndData,int row,string aim, int reverse) {stringstream ss;ss << reverse;string s1 = ss.str();string str = aim + "_"+s1+"_newA.csv";ofstream file(str);ifstream file1("A1.csv");string line;getline(file1, line);vector<string> data0;split(line, data0);file << data0[0] << "," << data0[row] << endl;for (int i = 0; i < NewNameAndData.size(); i++) {file << NewNameAndData[i].first << "," << NewNameAndData[i].second << endl;}cout << "文件已经保存在"<< str <<"中。";return;}private:void split(string line, vector<string>& linedatas) {string linedata;for (int i = 0; i < line.length();) {if (line[i] == ',') {linedata = line.substr(0, i);linedatas.push_back(linedata);line = line.substr(i + 1, line.length());i = 0;}else i++;}return;}
};int main()
{Solution solution;vector<string> rownames=solution.getRownames();// 用户输入目标名string aim;cout << "请输入目标名: ";cin >> aim;int row=solution.findRowname(rownames, aim);//cout << row;vector<pair<string, double>> NameAndData = solution.getNameAndData(row);// 用户输入保留行数int reverse;cout << "请输入保留行数: ";cin >> reverse;vector<pair<string, double>> NewNameAndData = solution.getNewNameAndData(NameAndData, reverse);solution.getNewCsv(NewNameAndData,row,aim,reverse);return 0;
}


http://www.ppmy.cn/ops/93376.html

相关文章

千里江山图,自动化成诗:Expect脚本详解——从入门到进阶的自动化利器

目录 引言 Expect脚本基础 什么是Expect 基本语法 进阶应用 错误处理 正则表达式 并发处理 使用Shell脚本管理多个Expect脚本 在Expect脚本内部模拟并发 脚本复用与模块化 总结 引言 在自动化运维和测试领域&#xff0c;Expect脚本无疑是一把强大的利器。它以其灵…

深入解析 CentOS 中的 ifcfg-eth0 配置文件

深入解析 CentOS 中的 ifcfg-eth0 配置文件 1. 引言 在 CentOS 系统中&#xff0c;ifcfg-eth0 是网络接口配置文件的标准命名格式&#xff0c;其中 eth0 表示第一个以太网接口。正确配置这些文件对确保网络连接的稳定性和可靠性至关重要。本文将详细介绍 ifcfg-eth0 文件的所…

20240813 每日AI必读资讯

Flux生成网红博主因太逼真爆火&#xff01;有人用Claude写代码识破“AI美女” - Flux生成的情侣合照逼真程度达到恐怖级别&#xff0c;挑战人类视觉辨识能力。 - 网友发现Flux生成的照片几乎完美&#xff0c;但仍有细微瑕疵可供识别。 - 有人利用Flux等工具制作逼真的YouTub…

React 后台管理项目 入门项目 简洁清晰保姆级内容讲解

序章 React Hook的后台管理项目&#xff0c;从0到1搭建&#xff0c;内容非常丰富涵盖项目搭建、路由配置、用户鉴权、首页报表、用户列表、前后端联调等功能&#xff0c;推荐指数&#xff1a;5颗星&#xff01; 视频学习链接: React 通用后台管理-零基础从0到1详细的入门保姆…

Springboot 实现 Modbus Rtu 协议接入物联网设备

Modbus RTU 技术教程 引言 Modbus是一种开放标准的通信协议,它最初由Modicon(现施耐德电气)在1979年发布,旨在让可编程逻辑控制器(PLC)之间能够进行通信。随着时间的发展,Modbus已经成为工业自动化领域中最常用的通信协议之一,尤其适用于连接工业电子设备。本文将详细…

Flink SQL 基础操作

Flink SQL是建立在Apache Flink之上的SQL处理引擎&#xff0c;它允许用户以SQL的方式处理流数据和批数据。以下是一些Flink SQL的基础操作&#xff1a; 一、环境准备 1.启动flink集群 ./start-cluster.sh启动sql-client ./sql-client.sh二、数据源定义 创建表&#xff08;…

C++ STL专题 list的底层实现

目录 1.模拟实现list 2.节点模板讲解 3.迭代器模板讲解 3.1为什么template 有三个类型参数 (1).class T (2).class ref (3).class ptr 3.2 *重载 3.3 ->重载 3.4 前置和后置的重载 3.5 前置--和--后置的重载 3.6 和!的重载 4. list模板讲解 4.1 begin()函数 …

《python语言程序设计》第6章第48题,格式化一个整型数 格式化整数为指定宽度。

def formatTest():number eval(input("Enter an integer: "))width eval(input("Enter the width: "))a format(number, f"0>{width}d")print(f"The formatted number is {a}")formatTest()第6章结束。