【问题标题】:CSVHelper, C#, ListCSVHelper、C#、列表
【发布时间】:2020-04-08 18:12:57
【问题描述】:

我正在尝试从第一行有以下记录的 csv 文件中读取多个记录类型

身份证, 姓名, 值的数量

第二行有

日期, 转移, 值[0..n], 质量

在原始 csvhelper example 的帮助下,我可以阅读原始行,但我无法弄清楚如何向 BarMap 传递需要聚合的值的数量

fooRecords.Add(csv.GetRecord<Foo>()); Foo.numValue

barRecords.Add(csv.GetRecord<Bar>());

public sealed class BarMap : ClassMap<Bar>
{
    public BarMap()
    {
        Map(m => m.date).Index(1);
        Map(m => m.shift).Index(2);
        //Aggregation of values 1 ..n goes here
        Map(m => m.quality).Index(n+1);

    }
}

如果有人可以帮助我,我将不胜感激。

【问题讨论】:

  • 如果没有固定数量的值,例如每行总是有相同数量的值,那么我想这个助手会遇到困难,因为它正在映射固定类并且不希望处理数组/列表。我认为您要么需要直接询问作者,要么自己动手。
  • 我在想的是,如果我可以将 numValues 传递给 Bar 映射器类,我应该能够迭代这些值以获取聚合。这看起来有可能吗?
  • 如果总是有相同数量的值,这听起来是可行的。如果每行有不同数量的值,那就更难了。
  • 你能给我一个相同数量值的例子吗?然后我会尝试这个想法,看看我如何使它适用于动态值。
  • 不使用 CSVHelper 并仅使用 streamreader 解析文件可能很容易。

标签: c# csvhelper


【解决方案1】:

如果要进行聚合,可以使用ConvertUsinghttps://joshclose.github.io/CsvHelper/examples/configuration/class-maps/inline-type-conversion

函数传入IReaderRow,您需要返回设置到属性的值。由于您拥有该行,因此您可以从任何字段中提取您想要的任何内容并创建设置的值。

例子:

void Main()
{
    var s = new StringBuilder();
    s.AppendLine("Id,A,B");
    s.AppendLine("1,2,3");
    using (var reader = new StringReader(s.ToString()))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        csv.Configuration.RegisterClassMap<FooMap>();
        csv.GetRecords<Foo>().ToList().Dump();
    }
}

public class Foo
{
    public int Id { get; set; }
    public int Sum { get; set; }
}

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Map(m => m.Id);
        Map(m => m.Sum).ConvertUsing(row => row.GetField<int>("A") + row.GetField<int>("B"));
    }
}

如果您希望将所有其他字段放入 List 或类似的名称中,您可以这样做。

void Main()
{
    var s = new StringBuilder();
    s.AppendLine("Id,A,B");
    s.AppendLine("1,2,3");
    using (var reader = new StringReader(s.ToString()))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        csv.Configuration.RegisterClassMap<FooMap>();
        csv.GetRecords<Foo>().ToList().Dump();
    }
}

public class Foo
{
    public int Id { get; set; }
    public List<int> TheRest { get; set; }
}

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Map(m => m.Id);
        Map(m => m.TheRest).Index(1);
    }
}

你也可以指定一个结束索引。

【讨论】:

  • 谢谢乔希。关于 ConvertUsing 的好指针。我最终做了``` Map(m => m.date).Index(1);地图(m => m.shift).Index(2); Map(m => m.IntervalValue).ConvertUsing(row => { double sumVal = 0; { for (int i = 0; i (i + 2) ; } }; 返回 sumVal; });地图(m => m.quality).Index(13); //2 个字段 + 10 个数字 ```
  • 这里还有一个问题,由于值的数量,我已经硬编码了 10,然后是 13。我可以从 Foo 类传递它。它只是一个告诉我在 Bar 类中期望的整数数量的数字.这些数字前后还有其他字段
  • 如果不是逐行的,可以在FooMap添加构造函数参数。然后使用new 创建地图并注册实例。 RegisterClassMap(fooMap)
  • 实际上是每行。每隔一行告诉我下一行有多少个数字。模式还在继续。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多