【问题标题】:C# Read column from CSV file only if column name exists in listC# 仅当列表中存在列名时才从 CSV 文件中读取列
【发布时间】:2021-10-09 17:01:33
【问题描述】:

我有一个从文件读取到列表中的列标题列表:

// Read column headers from text file
List<string> colHeads = new List<string>();
string[] lines = File.ReadAllLines("C:\\DATA\\MLData\\colHeads.txt");
string[] spl = new string[100];

foreach (string line in lines)
{
    spl = line.Split('=');
    colHeads.Add(spl[0].Trim());
}

然后我想读取一个 CSV 文件,但只读取列表中的列:

// Read CSV file
string[] lines = File.ReadAllLines("C:\\DATA\\MLData\hist.csv");
string[] spl = new string[500];

foreach (string line in lines)
{
        spl = line.Split(',');
        var rec = new Record()
        {
            Name = spl[1],
            ident = float.Parse(spl[4], CultureInfo.InvariantCulture.NumberFormat),
            location = float.Parse(spl[5], CultureInfo.InvariantCulture.NumberFormat),
            ...
            ...
        };
}

colHeads.txt 示例....

Name
ident
location
...

hist.csv 示例...

Name,yob,ident,level,location,score1
John B,1981,23,3,GB,54

hist.csv 中的列比 colHeads.txt 多,因此我需要一种按列名而不是列号读取 csv 文件的方法,忽略不在列表中的列。我分配的变量与列名完全匹配。

【问题讨论】:

  • 如果 Record 是一个类或结构,其字段或属性名称与 excel 列名称相同,您可以使用反射动态分配它
  • 您听说过像CSV Helper 这样的库吗?您可以将线条作为对象来处理,并做很多工作人员。
  • CSV 文件的第一行是否包含标题?
  • 向我们展示 colHeads.txt 和几行 hist.csv。
  • Bijan,是的,它是一个类并且名称匹配,我将如何使用“反射”? Alexander:是的,我已经更新了问题。

标签: c# csv


【解决方案1】:

假设colHeads 包含标题名称列表,您可以尝试这样的操作。

location = colHeads.Contains("location") ? float.Parse(spl[5], CultureInfo.InvariantCulture.NumberFormat) : 0

如果可用列的集合始终相同,而您只是想更改所读取的列,则这对于基本用途来说可能工作得很好。

【讨论】:

  • 对不起,我应该指定,csv文件中的数据不一样,它有很多不使用的列,所以我需要将列名与变量名匹配(它们正是一样)。
  • @user2096512 我调整了我的假设。我的意思是它假设可用列的集合总是相同的,但行会不同。或者,您是说每个 CSV 文件总是有一组不同的列?
  • 我现在使用 csvHelper 完成了它,它具有自动将类变量与标题匹配的功能:joshclose.github.io/CsvHelper/examples/reading/…
  • @user2096512 太棒了。 CSVHelper 是一个很棒的工具。
【解决方案2】:
var colHeads = File.ReadLines("colHeads.txt").ToHashSet();
var lines = File.ReadLines("hist.csv");
var headers = lines.First().Split(',');
var indexes = new Dictionary<string, int>();
var records = new List<Record>();

for (int i = 0; i < headers.Length; i++)
{
    indexes[headers[i]] = colHeads.Contains(headers[i]) ? i : -1;
}

int nameIndex = indexes[nameof(Record.Name)];
int identIndex = indexes[nameof(Record.ident)];
int locationIndex = indexes[nameof(Record.location)];
//...

foreach (var line in lines.Skip(1))
{
    var values = line.Split(',');
    var record = new Record();
    records.Add(record);

    if (nameIndex >= 0) record.Name = values[nameIndex];
    if (identIndex >= 0) record.ident = float.Parse(values[identIndex]);
    if (locationIndex >= 0) record.location = values[locationIndex];
    //...
}

首先,我们从 hist.csv 文件中读取标题并分配索引。
接下来,使用这些索引,我们设置记录的属性。

【讨论】:

    猜你喜欢
    • 2018-01-02
    • 1970-01-01
    • 2014-06-12
    • 2021-11-11
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多