如何用C#按指定日期筛选CSV文件行并获取对应value值
问题
我有一个表头为date;clock;value的CSV文件,需要筛选出指定日期的行并获取对应的value值。例如指定日期20.08.22时,预期结果为130(对应CSV行:20.08.22;08:04;130)。目前已编写了使用TextFieldParser读取CSV文件内容的C#代码,请问如何实现该筛选功能?
原代码片段:
private void Werte_aus_CSV_auslesen() { var path = @"E:\werte.csv"; using (TextFieldParser csvParser = new TextFieldParser(path)) { csvParser.CommentTokens = new string[] { "#" }; csvParser.SetDelimiters(new string[] { ";" }); csvParser.HasFieldsEnclosedInQuotes = true; // Skip the row with the column names csvParser.ReadLine(); while (!csvParser.EndOfData) { // Read current line fields, pointer moves to the next line. fields = csvParser.ReadFields(); datum.Add(fields[0]); uhrzeit.Add(fields[1]); wert.Add(double.Parse(fields[2], CultureInfo.InvariantCulture)); } } }
解决方案
可以根据实际需求选择以下两种实现方式:
方式一:读取时直接筛选(节省内存)
如果不需要保留所有CSV数据,仅需目标日期的value,可以在读取每行时直接判断日期,匹配则提取值,无需存储全部数据:
// 定义要筛选的目标日期 string targetDate = "20.08.22"; // 存储匹配到的value List<double> matchedValues = new List<double>(); private void Werte_aus_CSV_auslesen() { var path = @"E:\werte.csv"; using (TextFieldParser csvParser = new TextFieldParser(path)) { csvParser.CommentTokens = new string[] { "#" }; csvParser.SetDelimiters(new string[] { ";" }); csvParser.HasFieldsEnclosedInQuotes = true; // 跳过表头 csvParser.ReadLine(); while (!csvParser.EndOfData) { string[] fields = csvParser.ReadFields(); // 判断当前行日期是否匹配目标日期 if (fields[0] == targetDate) { // 安全解析value并添加到结果列表 if (double.TryParse(fields[2], CultureInfo.InvariantCulture, out double value)) { matchedValues.Add(value); } } } } // 处理匹配结果,示例取第一个匹配值 if (matchedValues.Count > 0) { double result = matchedValues[0]; // 后续逻辑:使用result } }
方式二:读取全部数据后再筛选
如果需要保留所有CSV数据供后续操作使用,可以在读取完成后通过列表索引匹配筛选:
// 假设已定义全局列表 List<string> datum = new List<string>(); List<string> uhrzeit = new List<string>(); List<double> wert = new List<double>(); private void Werte_aus_CSV_auslesen() { var path = @"E:\werte.csv"; using (TextFieldParser csvParser = new TextFieldParser(path)) { csvParser.CommentTokens = new string[] { "#" }; csvParser.SetDelimiters(new string[] { ";" }); csvParser.HasFieldsEnclosedInQuotes = true; csvParser.ReadLine(); while (!csvParser.EndOfData) { string[] fields = csvParser.ReadFields(); datum.Add(fields[0]); uhrzeit.Add(fields[1]); wert.Add(double.Parse(fields[2], CultureInfo.InvariantCulture)); } } // 筛选指定日期的value string targetDate = "20.08.22"; List<double> matchedValues = new List<double>(); for (int i = 0; i < datum.Count; i++) { if (datum[i] == targetDate) { matchedValues.Add(wert[i]); } } // 使用匹配结果 if (matchedValues.Any()) { double firstResult = matchedValues.First(); // 后续操作 } }
优化建议:用实体类封装数据
使用平行列表存储数据易出错,建议定义实体类封装每行数据,提升代码可维护性:
public class CsvData { public string Date { get; set; } public string Clock { get; set; } public double Value { get; set; } } private void Werte_aus_CSV_auslesen() { var path = @"E:\werte.csv"; List<CsvData> allData = new List<CsvData>(); string targetDate = "20.08.22"; using (TextFieldParser csvParser = new TextFieldParser(path)) { csvParser.CommentTokens = new string[] { "#" }; csvParser.SetDelimiters(new string[] { ";" }); csvParser.HasFieldsEnclosedInQuotes = true; csvParser.ReadLine(); while (!csvParser.EndOfData) { string[] fields = csvParser.ReadFields(); if (double.TryParse(fields[2], CultureInfo.InvariantCulture, out double value)) { allData.Add(new CsvData { Date = fields[0], Clock = fields[1], Value = value }); } } } // 筛选目标日期的value var matchedValues = allData.Where(d => d.Date == targetDate).Select(d => d.Value).ToList(); if (matchedValues.Any()) { double result = matchedValues.First(); // 后续操作 } }
内容的提问来源于stack exchange,提问作者Vik0809
相关产品推荐
相关产品推荐

