14

我正在使用CSVHelper读取大量数据

我想知道是否可以读取最后一n列并将它们转换为列表

"Name","LastName","Attribute1","Attribute2","Attribute3"

并将数据塑造成这样的东西

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public IList<string> Attributes { get; set; }
}

我希望一步完成,我敢肯定我可以有一个中间步骤,在其中我放入一个具有匹配属性属性的对象,但最好在一个单一的

4

4 回答 4

23

这可以作为映射器。

public sealed class PersonMap : CsvClassMap<Person>
{
    private List<string> attributeColumns = 
        new List<string> { "Attribute1", "Attribute2", "Attribute3" };

    public override void CreateMap()
    {
        Map(m => m.FirstName).Name("FirstName").Index(0);
        Map(m => m.LastName).Name("LastName").Index(1);
        Map(m => m.Attributes).ConvertUsing(row =>
            attributeColumns
                .Select(column => row.GetField<string>(column))
                .Where(value => String.IsNullOrWhiteSpace(value) == false)
            );
    }
}

那么你只需要这样的东西

using (var reader = new CsvReader(new StreamReader(filePath)))
{
    reader.Configuration.RegisterClassMap<PersonMap>();
    while (reader.Read())
    {
        var card = reader.GetRecord<Person>();
    }
}
于 2013-06-28T11:32:16.560 回答
3

版本 3 支持读取和写入IEnumerable属性。您可以像以前一样使用IList<T>属性。您只需要指定字段的起始索引。

Map( m => m.Attributes ).Index( 2 );
于 2016-08-25T04:29:43.657 回答
2

我不知道这个库,所以以下可能有帮助或没有帮助。

如果您已经有一个IEnumerable<IEnumerable<string>>代表所有列的所有记录,则可以使用此 Linq 查询来List<Person>获取IList<string> Attributes

IEnumerable<IEnumerable<string>> allRecords = .....;
IEnumerable<Person> allPersons = allRecords
.Select(rec => 
{
    var person = new Person();
    person.FirstName = rec.ElementAt(0);
    person.LastName = rec.ElementAtOrDefault(1);
    person.Attributes = rec.Skip(2).ToList();
    return person;
}).ToList();

编辑:下载库,至少编译后,无法真正测试它:

IList<Person> allPersons = new List<Person>();
using (var reader = new CsvHelper.CsvReader(yourTextReader))
{
    while (reader.Read())
    {
        var person = new Person();
        person.FirstName = reader.CurrentRecord.ElementAt(0);
        person.LastName = reader.CurrentRecord.ElementAtOrDefault(1);
        person.Attributes = reader.CurrentRecord.Skip(2).ToList();
        allPersons.Add(person);
    }
}
于 2013-06-27T21:39:32.527 回答
2

您实际上不需要事先定义列名,您可以从FieldHeaders属性中获取它们。因此,在尼尔答案的更动态版本中,您可以这样定义Mapper

public sealed class PersonMap : CsvClassMap<Person> {
    public override void CreateMap() {
        Map(m => m.FirstName).Name("FirstName").Index(0);
        Map(m => m.LastName).Name("LastName").Index(1);
        Map(m => m.Attributes).ConvertUsing(row =>
            (row as CsvReader)?.FieldHeaders
                 .Where(header => header.StartsWith("Attribute"))
                 .Select(header => row.GetField<string>(header))
                 .Where(value => !string.IsNullOrWhiteSpace(value))
                 .ToList()
        );
    }
}
于 2016-04-26T14:19:30.230 回答