Чтение CSV-файла во вложенные объекты

У меня есть CSV-файл вроде

Title|Column|Value
A|Z1|1
A|Z1|2
A|Z1|3
A|Z2|1
A|Z2|5
B|Z3|4
B|Z3|6
....

Я хочу прочитать этот CSV-файл в следующей иерархии классов: (Я хочу получить список из MyClass)

class MyClass
{
    public string Title { get; set; }
    public List<Column> Columns { get; set; }
}
class Column
{
    public string Column { get; set; }
    public List<Value> Values { get; set; }
}
class Value
{
    public string Value { get; set; }
}

Я не могу понять, как этого добиться. До сих пор я пробовал:

class DTO
{
    public string Title { get; set; }
    public string Column { get; set; }
    public string Value { get; set; }
}

List<DTO> records = new List<DTO>();
using (var reader = new StreamReader(model.Path))
using (var csv = new CsvReader(reader))
{
    records = csv.GetRecords<DTO>().ToList();
}

var temp = records
    .GroupBy(x => x.Title)
    .Select(y => new
    {
        Title = y.Key,
        Columns = y.SelectMany(x => new { x.Column, x.Value }) //I am not sure how to proceed from here
    });

Проблема, с которой я столкнулся, заключается в том, как я могу продолжить группировку по столбцам и получить значения, или мне следует использовать другой подход?

Еще несколько пояснений к структуре csv: для каждого столбца может быть несколько значений, и для каждого заголовка может быть несколько столбцов.


person Segmentation Fault    schedule 24.06.2019    source источник


Ответы (1)


Для каждого столбца может быть несколько значений, и для каждого заголовка может быть несколько столбцов.

Это означает, что вам нужно повторить первый шаг и снова GroupBy по столбцам. Вы также должны использовать для этого те типы, которые вы уже реализовали. Не используйте анонимные типы:

IEnumerable<MyClass> temp = records
    .GroupBy(x => x.Title)
    .Select(y => new MyClass
    {
        Title = y.Key,
        Columns = y.GroupBy(x => x.Column)
        .Select( c => new Column
        {
            Column_ = c.Key,
            Values = c.Select(v => new Value
            {
                Value_ = v.Value
            }).ToList()
        }).ToList()
    });

    temp.Dump();

Результат (из дампа LINQPad):

введите описание изображения здесь

PS. Я изменил имена свойств, потому что компилятор не позволяет им называть точно так же, как класс.

class Column
{
    public string Column_ { get; set; }
    public List<Value> Values { get; set; }
}
class Value
{
    public string Value_ { get; set; }
}
person Mong Zhu    schedule 24.06.2019