当我有位置索引时将数据映射到列表
Mapping data to a list when I have the position index
(我正在使用 CSVHelper 包)
嗨,
我有一个 sbyte[]
数组,它保存 CSV 文件中每个 header 列的位置。数组定义如下,
public sbyte[] ColumnIndex = new sbyte[Enum.GetNames(typeof(MyEnum)).Length];
并说我有一个如下所示的 CSV 文件:
col1,col2,col3,col4
name1,empId1,241682-27638-USD-CIGGNT ,1
name2,empId2,241682-27638-USD-OCGGINT ,1
name3,empId3,241942-37190-USD-GGDIV ,2
name4,empId4,241942-37190-USD-CHYOF ,1
name5,empId5,241942-37190-USD-EQPL ,1
name6,empId6,241942-37190-USD-INT ,1
name7,empId7,242066-15343-USD-CYJOF ,3
name8,empId8,242066-15343-USD-CYJOF ,3
name9,empId9,242066-15343-USD-CYJOF ,3
name10,empId10,241942-37190-USD-GGDIV ,2
现在调用字节数组并传递 Enum
索引会返回 header 行中的那个位置:
int conversion = (int)MyEnum.col3;
ColumnIndex[conversion]);
returns 2
现在一切正常,但我似乎很难弄清楚如何根据我的位置索引将每一列及其信息映射到 List<string>
。
我尝试使用以下代码将所有字段放在一个 List<string>
中:
public List<string> ParseEntire(aliasType type, string PathToFile) {
List<string> result = new List<string>();
using (TextReader fileReader = File.OpenText(PathToFile)) {
var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
string value;
while (csv.Read()) {
for (int i = 0; csv.TryGetField<string>(i, out value); i++) {
result.Add(value);
}
}
}
return result;
}
然而,那是没有用的,因为我无法知道每个 header 的位置。我觉得使用 CSVHelper
包有一种更简单的方法,我只是把一个简单的任务复杂化了。任何帮助将不胜感激。
编辑:
对于以下Emun
public enum aliasType {
col5,
col4,
col3,
col2,
col1
}
执行将位置索引映射到 ColumnIndex
的代码后,它看起来像这样:
ColumnIndex {sbyte[4]}
[0] [-1]
[1] [3]
[2] [2]
[3] [1]
[4] [0]
我这样做主要是因为我不知道 header 行包含什么。因此,我尽可能多地提取信息,当我返回索引 -1 时,我知道该特定字段不存在。
更新:
以下代码使用 Intersect
与我尝试提取的同一 header 列的不同别名进行比较。
public List<string> HeaderColumnParser(aliasType type, string PathToFile) {
List<string> result = new List<string>();
using (TextReader fileReader = File.OpenText(PathToFile)) {
var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
CSVBOM extract = new CSVBOM("", CSVBOM.BOMFileType.csv);
csv.Read();
csv.ReadHeader();
string[] header = csv.Context.HeaderRecord;
IEnumerable<string> CommonHeaders;
foreach (aliasType foo in Enum.GetValues(typeof(aliasType))) {
int res = Convert.ToInt32(foo);
switch (res) {
case 0:
// get matching string
CommonHeaders = header.Intersect(ReferenceDesignatorAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 1:
CommonHeaders = header.Intersect(ManufacturersPartNumberAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 2:
CommonHeaders = header.Intersect(ValueAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 3:
CommonHeaders = header.Intersect(DescriptionShortAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 4:
CommonHeaders = header.Intersect(DescriptionLongAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 5:
CommonHeaders = header.Intersect(ManufacturerAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 6:
CommonHeaders = header.Intersect(DNIAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 7:
CommonHeaders = header.Intersect(DataSheetAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
default:
throw new Exception("Alias type is not recognized");
}
}
}
return result;
}
我的别名枚举和字符串数组:
public enum aliasType {
ReferenceDesignatorAliases,
ManufacturersPartNumberAliases,
ValueAliases,
DescriptionShortAliases,
DescriptionLongAliases,
ManufacturerAliases,
DNIAliases,
DataSheetAliases
}
//Returns -1 meaning not found
public sbyte[] ColumnIndex = new sbyte[Enum.GetNames(typeof(aliasType)).Length];
public string[] ReferenceDesignatorAliases = { "Reference Designator", "RefDes", "Designator", "Annotation" };
public string[] ManufacturersPartNumberAliases = { "Manufacturer's Part Number", "MPN", "PN", "part Number" };
public string[] ValueAliases = { "Value" };
public string[] DescriptionShortAliases = { "Description Short", "Description" };
public string[] DescriptionLongAliases = { "Description Long" };
public string[] ManufacturerAliases = { "Manufacturer", "MF" };
public string[] DNIAliases = { "DNI", "Do Not Install" };
public string[] DataSheetAliases = { "DataSheet", "Data Sheet" };
我相信我对你想要完成的事情有了更好的了解。如果这能解决您的问题,请告诉我。
public static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("MF,RefDes,MPN,Value");
writer.WriteLine("name1,empId1,241682-27638-USD-CIGGNT ,1");
writer.WriteLine("name2,empId2,241682-27638-USD-OCGGINT ,1");
writer.WriteLine("name3,empId3,241942-37190-USD-GGDIV ,2");
writer.WriteLine("name4,empId4,241942-37190-USD-CHYOF ,1");
writer.Flush();
stream.Position = 0;
string[] ReferenceDesignatorAliases = { "Reference Designator", "RefDes", "Designator", "Annotation" };
csv.Read();
csv.ReadHeader();
var result = new List<string>();
if (csv.Context.HeaderRecord.Intersect(ReferenceDesignatorAliases).Count() > 0)
{
while (csv.Read())
{
if (csv.TryGetField(csv.GetFieldIndex(ReferenceDesignatorAliases), out string value))
{
result.Add(value);
}
}
}
}
Console.ReadKey();
}
这是另一个选项,可以一次获取所有列,然后您可以将它们拆分成单独的列列表。
public class Program
{
public static void Main(string[] args)
{
List<Foo> records;
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("MF,RefDes,MPN,Value");
writer.WriteLine("name1,empId1,241682-27638-USD-CIGGNT ,1");
writer.WriteLine("name2,empId2,241682-27638-USD-OCGGINT ,1");
writer.WriteLine("name3,empId3,241942-37190-USD-GGDIV ,2");
writer.WriteLine("name4,empId4,241942-37190-USD-CHYOF ,1");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<FooClassMap>();
records = csv.GetRecords<Foo>().ToList();
}
if (!records.All(r => r.ReferenceDesignator == null))
{
var ReferenceResult = records.Select(r => r.ReferenceDesignator).ToList();
}
if (!records.All(r => r.Manufacturer == null))
{
var ManufacturerResult = records.Select(r => r.Manufacturer).ToList();
}
Console.ReadKey();
}
}
public class Foo
{
public string ReferenceDesignator { get; set; }
public string ManufacturersPartNumber { get; set; }
public int? Value { get; set; }
public string DescriptionShort { get; set; }
public string DescriptionLong { get; set; }
public string Manufacturer { get; set; }
public string Dni { get; set; }
public string DataSheet { get; set; }
}
public class FooClassMap : ClassMap<Foo>
{
public FooClassMap()
{
Map(m => m.ReferenceDesignator).Optional().Name("Reference Designator", "RefDes", "Designator", "Annotation");
Map(m => m.ManufacturersPartNumber).Optional().Name("Manufacturer's Part Number", "MPN", "PN", "part Number");
Map(m => m.Value).Optional();
Map(m => m.DescriptionShort).Optional().Name("Description Short", "Description");
Map(m => m.DescriptionLong).Optional().Name("Description Long");
Map(m => m.Manufacturer).Optional().Name("Manufacturer", "MF");
Map(m => m.Dni).Optional().Name("DNI", "Do Not Install");
Map(m => m.DataSheet).Optional().Name("DataSheet", "Data Sheet");
}
}
(我正在使用 CSVHelper 包)
嗨,
我有一个 sbyte[]
数组,它保存 CSV 文件中每个 header 列的位置。数组定义如下,
public sbyte[] ColumnIndex = new sbyte[Enum.GetNames(typeof(MyEnum)).Length];
并说我有一个如下所示的 CSV 文件:
col1,col2,col3,col4
name1,empId1,241682-27638-USD-CIGGNT ,1
name2,empId2,241682-27638-USD-OCGGINT ,1
name3,empId3,241942-37190-USD-GGDIV ,2
name4,empId4,241942-37190-USD-CHYOF ,1
name5,empId5,241942-37190-USD-EQPL ,1
name6,empId6,241942-37190-USD-INT ,1
name7,empId7,242066-15343-USD-CYJOF ,3
name8,empId8,242066-15343-USD-CYJOF ,3
name9,empId9,242066-15343-USD-CYJOF ,3
name10,empId10,241942-37190-USD-GGDIV ,2
现在调用字节数组并传递 Enum
索引会返回 header 行中的那个位置:
int conversion = (int)MyEnum.col3;
ColumnIndex[conversion]);
returns 2
现在一切正常,但我似乎很难弄清楚如何根据我的位置索引将每一列及其信息映射到 List<string>
。
我尝试使用以下代码将所有字段放在一个 List<string>
中:
public List<string> ParseEntire(aliasType type, string PathToFile) {
List<string> result = new List<string>();
using (TextReader fileReader = File.OpenText(PathToFile)) {
var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
string value;
while (csv.Read()) {
for (int i = 0; csv.TryGetField<string>(i, out value); i++) {
result.Add(value);
}
}
}
return result;
}
然而,那是没有用的,因为我无法知道每个 header 的位置。我觉得使用 CSVHelper
包有一种更简单的方法,我只是把一个简单的任务复杂化了。任何帮助将不胜感激。
编辑: 对于以下Emun
public enum aliasType {
col5,
col4,
col3,
col2,
col1
}
执行将位置索引映射到 ColumnIndex
的代码后,它看起来像这样:
ColumnIndex {sbyte[4]}
[0] [-1]
[1] [3]
[2] [2]
[3] [1]
[4] [0]
我这样做主要是因为我不知道 header 行包含什么。因此,我尽可能多地提取信息,当我返回索引 -1 时,我知道该特定字段不存在。
更新:
以下代码使用 Intersect
与我尝试提取的同一 header 列的不同别名进行比较。
public List<string> HeaderColumnParser(aliasType type, string PathToFile) {
List<string> result = new List<string>();
using (TextReader fileReader = File.OpenText(PathToFile)) {
var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
CSVBOM extract = new CSVBOM("", CSVBOM.BOMFileType.csv);
csv.Read();
csv.ReadHeader();
string[] header = csv.Context.HeaderRecord;
IEnumerable<string> CommonHeaders;
foreach (aliasType foo in Enum.GetValues(typeof(aliasType))) {
int res = Convert.ToInt32(foo);
switch (res) {
case 0:
// get matching string
CommonHeaders = header.Intersect(ReferenceDesignatorAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 1:
CommonHeaders = header.Intersect(ManufacturersPartNumberAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 2:
CommonHeaders = header.Intersect(ValueAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 3:
CommonHeaders = header.Intersect(DescriptionShortAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 4:
CommonHeaders = header.Intersect(DescriptionLongAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 5:
CommonHeaders = header.Intersect(ManufacturerAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 6:
CommonHeaders = header.Intersect(DNIAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
case 7:
CommonHeaders = header.Intersect(DataSheetAliases);
ColumnIndex[res] = extract.ExtractIndexHeader(CommonHeaders, header);
break;
default:
throw new Exception("Alias type is not recognized");
}
}
}
return result;
}
我的别名枚举和字符串数组:
public enum aliasType {
ReferenceDesignatorAliases,
ManufacturersPartNumberAliases,
ValueAliases,
DescriptionShortAliases,
DescriptionLongAliases,
ManufacturerAliases,
DNIAliases,
DataSheetAliases
}
//Returns -1 meaning not found
public sbyte[] ColumnIndex = new sbyte[Enum.GetNames(typeof(aliasType)).Length];
public string[] ReferenceDesignatorAliases = { "Reference Designator", "RefDes", "Designator", "Annotation" };
public string[] ManufacturersPartNumberAliases = { "Manufacturer's Part Number", "MPN", "PN", "part Number" };
public string[] ValueAliases = { "Value" };
public string[] DescriptionShortAliases = { "Description Short", "Description" };
public string[] DescriptionLongAliases = { "Description Long" };
public string[] ManufacturerAliases = { "Manufacturer", "MF" };
public string[] DNIAliases = { "DNI", "Do Not Install" };
public string[] DataSheetAliases = { "DataSheet", "Data Sheet" };
我相信我对你想要完成的事情有了更好的了解。如果这能解决您的问题,请告诉我。
public static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("MF,RefDes,MPN,Value");
writer.WriteLine("name1,empId1,241682-27638-USD-CIGGNT ,1");
writer.WriteLine("name2,empId2,241682-27638-USD-OCGGINT ,1");
writer.WriteLine("name3,empId3,241942-37190-USD-GGDIV ,2");
writer.WriteLine("name4,empId4,241942-37190-USD-CHYOF ,1");
writer.Flush();
stream.Position = 0;
string[] ReferenceDesignatorAliases = { "Reference Designator", "RefDes", "Designator", "Annotation" };
csv.Read();
csv.ReadHeader();
var result = new List<string>();
if (csv.Context.HeaderRecord.Intersect(ReferenceDesignatorAliases).Count() > 0)
{
while (csv.Read())
{
if (csv.TryGetField(csv.GetFieldIndex(ReferenceDesignatorAliases), out string value))
{
result.Add(value);
}
}
}
}
Console.ReadKey();
}
这是另一个选项,可以一次获取所有列,然后您可以将它们拆分成单独的列列表。
public class Program
{
public static void Main(string[] args)
{
List<Foo> records;
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("MF,RefDes,MPN,Value");
writer.WriteLine("name1,empId1,241682-27638-USD-CIGGNT ,1");
writer.WriteLine("name2,empId2,241682-27638-USD-OCGGINT ,1");
writer.WriteLine("name3,empId3,241942-37190-USD-GGDIV ,2");
writer.WriteLine("name4,empId4,241942-37190-USD-CHYOF ,1");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<FooClassMap>();
records = csv.GetRecords<Foo>().ToList();
}
if (!records.All(r => r.ReferenceDesignator == null))
{
var ReferenceResult = records.Select(r => r.ReferenceDesignator).ToList();
}
if (!records.All(r => r.Manufacturer == null))
{
var ManufacturerResult = records.Select(r => r.Manufacturer).ToList();
}
Console.ReadKey();
}
}
public class Foo
{
public string ReferenceDesignator { get; set; }
public string ManufacturersPartNumber { get; set; }
public int? Value { get; set; }
public string DescriptionShort { get; set; }
public string DescriptionLong { get; set; }
public string Manufacturer { get; set; }
public string Dni { get; set; }
public string DataSheet { get; set; }
}
public class FooClassMap : ClassMap<Foo>
{
public FooClassMap()
{
Map(m => m.ReferenceDesignator).Optional().Name("Reference Designator", "RefDes", "Designator", "Annotation");
Map(m => m.ManufacturersPartNumber).Optional().Name("Manufacturer's Part Number", "MPN", "PN", "part Number");
Map(m => m.Value).Optional();
Map(m => m.DescriptionShort).Optional().Name("Description Short", "Description");
Map(m => m.DescriptionLong).Optional().Name("Description Long");
Map(m => m.Manufacturer).Optional().Name("Manufacturer", "MF");
Map(m => m.Dni).Optional().Name("DNI", "Do Not Install");
Map(m => m.DataSheet).Optional().Name("DataSheet", "Data Sheet");
}
}