#csvhelper
#csvhelper
Вопрос:
Дело в том, что я анализирую файл, который выглядит примерно так.
Имя | Учетная запись |
---|---|
Foo клиент | 123 |
Клиент Bar | 456,789 |
В реальных данных я делаю еще кое-что, чтобы очистить учетную запись и т. Д., Но главное — ,
в столбце Account. Теперь я получаю IEnumerable с 2 записями, я бы хотел получить IEnumerable с 3 записями, разделив записи на запятую в столбце Account .
Вот так.
Имя | Учетная запись |
---|---|
Foo клиент | 123 |
Клиент Bar | 456 |
Клиент Bar | 789 |
Возможно ли это с помощью CSV Helper?
Ответ №1:
void Main()
{
using (var sReader = new StringReader("Name,AccountnFoo client,123nBar client,"456,789""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Read();
csvReader.ReadHeader();
var records = new List<Foo>();
while (csvReader.Read())
{
var name = csvReader.GetField("Name");
var account = csvReader.GetField("Account");
var splitAccounts = account.Split(",");
foreach(var item in splitAccounts)
{
records.Add(new Foo { Name = name, Account = int.Parse(item)});
}
}
records.Dump();
}
}
public class Foo
{
public string Name { get; set; }
public int Account { get; set; }
}
Обновление:
Каждая строка — это запись, поэтому вы действительно не можете создать новую запись, находясь за ClassMap
пределами строки. Что вы могли бы сделать , так это обернуть свой класс в другой класс , содержащий несколько List<MyClass>
записей , которые вы пытаетесь создать , а затем объединить их обратно в один List<MyClass>
. Если Account
можно ввести string
, MyClass
вы могли бы обойтись без отдельного MyClassMap
и просто позволить этому AutoMap()
вашему классу.
void Main()
{
using (var sReader = new StringReader("Name,AccountnFoo client,123nBar client,"456,789""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Configuration.RegisterClassMap<FooMap>();
csvReader.Configuration.RegisterClassMap<MyClassMap>();
var wrappedRecords = csvReader.GetRecords<Foo>();
var records = wrappedRecords.SelectMany(r => r.Clients).ToList();
records.Dump();
}
}
public class FooMap : ClassMap<Foo>
{
public FooMap()
{
Map(x => x.Clients).ConvertUsing(x =>
{
var records = new List<MyClass>();
var record = x.GetRecord<MyClass>();
var splitAccounts = x.GetField("Account").Split(",");
foreach (var item in splitAccounts)
{
records.Add(new MyClass { Name = record.Name, Account = int.Parse(item) });
}
return records;
});
}
}
public class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
Map(x => x.Name);
}
}
public class Foo
{
public List<MyClass> Clients { get; set; }
}
public class MyClass
{
public string Name { get; set; }
public int Account { get; set; }
}
Комментарии:
1. Это сработало бы, но я не упомянул, что я хотел бы выполнить преобразование на этапе преобразования столбца Account в карте классов, которую я использую.
2. Посмотрите, приблизит ли мое обновление вас к тому, чего вы пытаетесь достичь.
3. Спасибо за усилия, Дэвид. На самом деле я закончил тем, что позволил CSV Helper делать это, то есть просто разбирать строки, и после этого добавил еще один шаг очистки, чтобы обработать его с помощью нескольких строк Linq.