我有一个类对象的列表,其中又包含另一个类对象的列表。它们看起来像这样:
public class Column
{
public string ColName { get; set; }
public List<Item> ItemList { get; set; }
}
public class Item
{
public DateTime TimeStamp { get; set; }
public double Value { get; set; }
}
它们有两个重要属性:
- 所有列中
List<Item> ItemList
的Length
将相同。但是,我直到运行时才知道该长度。 - 每个列中
TimeStamp
的实际值将相同。换句话说,每个列中的TimeStamp
列表将是相同的。
如果您查看下面我编写的创建 Column
对象列表的模拟函数,您将获得一个清晰的图片。这是我的实际数据(从程序的其他地方获取)的准确描述:
private static List<Column> GetColumns()
{
var dt1 = DateTime.Now;
var dt2 = dt1.AddSeconds(1);
var dt3 = dt2.AddSeconds(1);
var dt4 = dt3.AddSeconds(1);
var col1 = new Column()
{
ColName = "ABC",
ItemList = new List<Item>
{
new Item() { TimeStamp = dt1, Value = 1 },
new Item() { TimeStamp = dt2, Value = 2 },
new Item() { TimeStamp = dt3, Value = 3 },
new Item() { TimeStamp = dt4, Value = 4 }
}
};
var col2 = new Column()
{
ColName = "XYZ",
ItemList = new List<Item>
{
new Item() { TimeStamp = dt1, Value = 4 },
new Item() { TimeStamp = dt2, Value = 3 },
new Item() { TimeStamp = dt3, Value = 2 },
new Item() { TimeStamp = dt4, Value = 1 }
}
};
var col3 = new Column()
{
ColName = "KLM",
ItemList = new List<Item>
{
new Item() { TimeStamp = dt1, Value = 1 },
new Item() { TimeStamp = dt2, Value = 2 },
new Item() { TimeStamp = dt3, Value = 4 },
new Item() { TimeStamp = dt4, Value = 8 }
}
};
var list = new List<Column>
{
col1,
col2,
col3,
};
return list;
}
重要提示是,我不会在运行时知道
List<Column>
的长度,也不会知道它们内部的 ItemList
的长度。此外,我也不会在运行时知道每个列的名称。现在我的目标是将这些信息写入以下格式的 CSV
文件。
我觉得这里应该使用动态的
方式,所以我从这个开始:
var columns = GetColumns();
var timeStamps = columns.First().ItemList.Select(x => x.TimeStamp).ToList();
var writeList = new List<dynamic>();
for (int i = 0; i < timeStamps.Count; i++)
{
dynamic csvItem = new ExpandoObject();
csvItem.TimeStamp = timeStamps[i];
// How to get columns?
writeList.Add(csvItem);
}
using (var writer = new StreamWriter("output.csv"))
{
using (var csv = new CsvHelper.CsvWriter(writer))
{
csv.WriteRecords(writeList);
}
}
这是一个开始,但由于我不知道将拥有多少列和它们的名称,所以不确定如何继续。在这里使用
dynamic
不是一个选项吗?或者我可以完全放弃使用
CSVHelper
,像下面这样从头开始编写,但有点凌乱。我需要两次迭代列列表,并总共需要三个循环。如果可能的话,我正在寻找更优雅的解决方案。var columns = GetColumns();
var timeStamps = columns.First().ItemList.Select(x => x.TimeStamp).ToList();
var headers = "TimeStamp";
foreach (var col in columns)
{
headers += "," + col.ColName;
}
using (var fs = new FileStream("output.csv", FileMode.Create, FileAccess.Write))
{
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(headers);
for (int i = 0; i < timeStamps.Count; i++)
{
var line = timeStamps[i].ToString("yyyy/MM/dd HH:mm:ss");
foreach (var col in columns)
{
line += "," + col.ItemList[i].Value;
}
sw.WriteLine(line);
}
}
}
StringBuilder
创建整个csv结构,然后将其保存为csv呢?这比第二种方法要快得多。至于csvHelper,对于像这样简单的东西,我甚至不会费心添加nuget依赖项。 - Kosala W