英文:
converting csvhelper list into a dictionary<string, object>
问题
我有一个看起来像这样的CSV文件:
23.75,-71.14026637566099,23.26,-68.14,X (mm),Y (mm),X (mm),Y (mm),X (mm),Y (mm)
...
获取这个数据对我来说不是问题,这是我的工作代码:
class CsvHelperTester
{
...
}
我想将这个列表转换成一个字典,类似于List<Dictionary<string,object>>
。因此,数据需要转换成水平数据,像这样:
Y(mm) : -61.232543
Y2(mm) : 63.23532
然而,我不确定如何进行这种类型的转换,或者是否有更好的解决方案。我无法控制这个CSV,所以它会按照这种方式传递给我。我甚至不知道数据是否可以转换成我需要的字典。我需要将数据转换成这种格式,因为我打算将这些数据转换成一个DataTable并发送到MongoDB,以便可以很好地读取它。任何帮助将不胜感激,谢谢!
英文:
I have a csv file that looks like this:
23.75,-71.14026637566099,23.26,-68.14,X (mm),Y (mm),X (mm),Y (mm),X (mm),Y (mm)
75.0,0.0,72.0,0.0,-70.8744,-11.0272,-62.1812,-22.0121,1.1013,5.3621
74.62531239585194,7.487506248512112,71.64029990001787,7.188005998571628,-66.1987,26.7792,-61.3198,24.1895,5.8892,34.9479
73.50499333809312,14.90019980962959,70.5647936045694,14.304191817244408,-54.6861,21.1036,-60.9723,-29.1698,,
71.65023668442045,22.16401549960047,68.78422721704364,21.27745487961645,-53.3795,20.8321,-57.5484,-7.0754,,
69.07957455021638,29.206375673148788,66.31639156820773,28.038120646222836,-44.5103,16.9127,-50.7663,34.2947,,
65.81869214177796,35.95691539531523,63.18594445610684,34.518638779502616,,,-48.7116,52.8106,,
61.90017111822588,42.34818550462765,59.42416427349683,40.65425808444255,,,-39.5089,41.8543,,
57.363164046336635,48.31632654282683,55.06863748448316,46.38367348111376,,,-38.6843,-45.1223,,
52.253003201037416,53.8017068174642,50.16288307299591,51.649638544765644,,,-37.7029,40.9664,,
46.62074762029984,58.74951822206125,44.75591771548784,56.399537493178805,,,-36.1945,7.7452,,
40.52267294011048,63.11032386059223,38.90176602250607,60.58591090616855,,,-33.1654,-12.0199,,
34.01970910691831,66.84055200460764,32.65892074264157,64.16692992442336,,,-27.4216,65.4545,,
27.17683158575052,69.90293144754197,26.089758322320485,67.1068141896403,,,-26.9546,-27.5354,,
20.06241214684405,72.26686390628947,19.25991566097029,69.37618935003789,,,-25.4676,24.2481,,
12.747535717518062,73.90872974913452,12.237634288817338,70.95238055916914,,,-19.3518,-53.9162,,
5.305290125077701,74.81212399530408,5.093078520074609,71.81963903549192,,,-15.8018,36.0254,,
-2.1899641725966776,74.96802022811288,-2.102365605692795,71.96929941898837,,,-12.8175,26.027,,
-9.663337072164381,74.37486078393515,-9.27680358927779,71.39986635257773,,,-12.8157,33.5647,,
-17.040157101981563,73.03857231586463,-16.358550817902273,70.11702942323005,,,-12.6135,14.0177,,
-24.246717514762796,70.97250657655607,-23.276848814172258,68.13360631349384,,,-12.5522,44.1962,,
-31.21101274103571,68.19730701192611,-29.962572231394255,65.46941473144908,,,-11.0237,4.4988,,
-37.86345784498934,64.74070249866551,-36.34891953118974,62.151074398718904,,,-11.014,15.0086,,
Getting this data is not a problem for me, here is my working code.
class CsvHelperTester
{
static void Main(string[] args)
{
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = false,
MissingFieldFound = null,
ShouldSkipRecord = args => args.Row.Parser.Record.All(String.IsNullOrEmpty)
};
using (var reader = new StreamReader("C:\\Users\\eyoung\\Desktop\\parse test files\\Data.csv"))
using (var csv = new CsvReader(reader, config))
{
var SicaGraphData = new List<SicaGraphData>();
while (csv.Read())
{
SicaGraphData.Add(csv.GetRecord<SicaGraphData>());
}
}
}
public class SicaGraphData
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
public string Value4 { get; set; }
[Name("X (mm)")]
public string X { get; set; }
[Name("Y (mm)")]
public string Y { get; set; }
[Name("X2 (mm)")]
public string X2 { get; set; }
[Name("Y2 (mm)")]
public string Y2 { get; set; }
[Name("X3 (mm)")]
public string X3 { get; set; }
[Name("Y3 (mm)")]
public string Y3 { get; set; }
}
}
What I want to do is convert this lost list into a dictionary, like List<Dictionary<string,object>> So the data needs to be converted into horizontal data, like this:
Y(mm) : -61.232543
Y2(mm) : 63.23532
However, I'm not sure how to do this type of conversion or if there is a better solution. I have no control over this csv, so this is just how it will come to me. I don't even know if the data can be converted into the dictionary that I need. I need the data converted into this format, as I'm going to convert this data into a datatable and send it to MongoDB, so it can be read nicely. Any help would be greatly appreciated, thanks!
答案1
得分: 1
这可以通过反射来实现。只是指出反射比从 SicaGraphData 类写出转换为字典的方式要慢,但认为这是一个展示它如何工作的好用例。
代码只是一个示例,使用反射来检查属性和值可能在创建复杂类或使用泛型时会有些棘手。
我创建了两种方法。第一种是根据问题将数据转换为输出的方法。这种方法实际上不需要反射,你可以轻松编写一个方法将行映射到字典。
这是一个简单的映射/选择函数。
public static List<Dictionary<string, object?>> PivotRecord(List<SicaGraphData> data){
return data.Select(row => MapToDictionary(row)).ToList();
}
private static Dictionary<string, object?> MapToDictionary(SicaGraphData row) {
var dictionary = new Dictionary<string, object?>(){};
foreach(var prop in row.GetType().GetProperties()) {
var cellValue = prop.GetValue(row, null);
dictionary.Add(prop.Name, cellValue);
}
return dictionary;
}
第二种方式将数据转换为带有值列表的字典。这可以看作是一个"Reduce"函数。
public static Dictionary<string, List<object?>> PivotDataSet(List<SicaGraphData> data){
var dictionary = new Dictionary<string, List<object?>>();
var properties = typeof(SicaGraphData).GetProperties();
foreach(var row in data) {
foreach(var prop in properties) {
var cellValue = prop.GetValue(row, null);
if (dictionary.TryGetValue(prop.Name, out var list)) {
list.Add(cellValue);
} else {
dictionary.Add(prop.Name, new List<object?>(){ cellValue});
}
}
}
return dictionary;
}
英文:
This could be done using reflection. Just stating that reflection will be slower than writing out the conversion from the SicaGraphData class to a dictionary but thought this is a good use case for show casing how it works.
The code is just an example, checking properties and values using reflection can be a little bit trickier if you create complex classes or using generics.
I've created two approaches. The first to convert the data into the output based on the question. This approach really doesn't need reflection, you can easily write a method to map a row to a dictionary.
This is a simple map/select function.
public static List<Dictionary<string, object?>> PivotRecord(List<SicaGraphData> data){
return data.Select(row => MapToDictionary(row)).ToList();
}
private static Dictionary<string, object?> MapToDictionary(SicaGraphData row) {
var dictionary = new Dictionary<string, object?>(){};
foreach(var prop in row.GetType().GetProperties()) {
var cellValue = prop.GetValue(row, null);
dictionary.Add(prop.Name, cellValue);
}
return dictionary;
}
The second variance converting the data into a dictionary with a list of values. This can be seen as a Reduce function.
public static Dictionary<string, List<object?>> PivotDataSet(List<SicaGraphData> data){
var dictionary = new Dictionary<string, List<object?>>();
var properties = typeof(SicaGraphData).GetProperties();
foreach(var row in data) {
foreach(var prop in properties) {
var cellValue = prop.GetValue(row, null);
if (dictionary.TryGetValue(prop.Name, out var list)) {
list.Add(cellValue);
} else {
dictionary.Add(prop.Name, new List<object?>(){ cellValue});
}
}
}
return dictionary;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论