C# 将字典列表转换为数据表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15293653/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Coverting List of Dictionary to DataTable
提问by Simsons
Currently we are doing this by looping through each value of list and dictionary:
目前我们通过循环遍历列表和字典的每个值来做到这一点:
private DataTable ChangeToDictionary(List<Dictionary<string,int>> list)
{
DataTable datatTableReturn = new DataTable();
if (list.Count() > 0)
{
Dictionary<string, int> haeders = list.ElementAt(0);
foreach (var colHead in haeders)
{
datatTableReturn.Columns.Add(colHead.Key);
}
}
foreach (var row in list)
{
DataRow dataRow = datatTableReturn.NewRow();
foreach (var col in row)
{
dataRow[col.Key] = col.Value;
}
datatTableReturn.Rows.Add(dataRow);
}
return datatTableReturn;
}
But is there a better way? Looping through so many times doesn't feel good
但是有更好的方法吗?循环这么多次感觉不太好
回答by Nikola Radosavljevi?
Speed, elegance and reusability don't go together. You always choose more important one, and try to balance other two.
速度、优雅和可重用性不能同时存在。你总是选择更重要的一个,并尝试平衡其他两个。
Faster the code, uglier it is. Prettier it is, less reusable it is.
代码越快,越丑。它更漂亮,可重用性更低。
Here's an example of "elegant" solution, but that goes with it not being very readable.
这是一个“优雅”解决方案的例子,但它的可读性不是很好。
private static DataTable ToDictionary(List<Dictionary<string, int>> list)
{
DataTable result = new DataTable();
if (list.Count == 0)
return result;
result.Columns.AddRange(
list.First().Select(r => new DataColumn(r.Key)).ToArray()
);
list.ForEach(r => result.Rows.Add(r.Select(c => c.Value).Cast<object>().ToArray()));
return result;
}
回答by Jodrell
How about something like the code below?
像下面的代码怎么样?
Good, because it iterates each row exactly once. It should be pretty quick, I've included obvious exceptions to make the code safer.
很好,因为它只迭代每一行一次。它应该很快,我已经包含了明显的例外以使代码更安全。
private static DataTable DictionariesToDataTable<T>(
IEnumerable<IDictionary<string, T>> source)
{
if (source == null)
{
return null;
}
var result = new DataTable();
using (var e = source.GetEnumerator())
{
if (!e.MoveNext())
{
return result;
}
if (e.Current.Keys.Length == 0)
{
throw new InvalidOperationException();
}
var length = e.Current.Keys.Length;
result.Columns.AddRange(
e.Current.Keys.Select(k => new DataColumn(k, typeof(T))).ToArray());
do
{
if (e.Current.Values.Length != length)
{
throw new InvalidOperationException();
}
result.Rows.Add(e.Current.Values);
}
while (e.MoveNext());
return result;
}
}
回答by John Kraft
The answers above don't address the issue of the dictionary having more than 1 row. This solution addresses the issue.
上面的答案没有解决字典超过 1 行的问题。此解决方案解决了该问题。
static DataTable ToDataTable(List<Dictionary<string, int>> list)
{
DataTable result = new DataTable();
if (list.Count == 0)
return result;
var columnNames = list.SelectMany(dict=>dict.Keys).Distinct();
result.Columns.AddRange(columnNames.Select(c=>new DataColumn(c)).ToArray());
foreach (Dictionary<string,int> item in list)
{
var row = result.NewRow();
foreach (var key in item.Keys)
{
row[key] = item[key];
}
result.Rows.Add(row);
}
return result;
}
static void Main(string[] args)
{
List<Dictionary<string, int>> it = new List<Dictionary<string, int>>();
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("a", 1);
dict.Add("b", 2);
dict.Add("c", 3);
it.Add(dict);
dict = new Dictionary<string, int>();
dict.Add("bob", 34);
dict.Add("tom", 37);
it.Add(dict);
dict = new Dictionary<string, int>();
dict.Add("Yip Yip", 8);
dict.Add("Yap Yap", 9);
it.Add(dict);
DataTable table = ToDictionary(it);
foreach (DataColumn col in table.Columns)
Console.Write("{0}\t", col.ColumnName);
Console.WriteLine();
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
Console.Write("{0}\t", row[column].ToString());
Console.WriteLine();
}
Console.ReadLine();
}
And the output looks like...
输出看起来像......
a b c bob tom Yip Yip Yap Yap
1 2 3
34 37
8 9
回答by Dustin Kingen
Try this:
尝试这个:
private DataTable GetDataTableFromDictionaries<T>(List<Dictionary<string, T>> list)
{
DataTable dataTable = new DataTable();
if (list == null || !list.Any()) return dataTable;
foreach (var column in list.First().Select(c => new DataColumn(c.Key, typeof(T))))
{
dataTable.Columns.Add(column);
}
foreach (var row in list.Select(
r =>
{
var dataRow = dataTable.NewRow();
r.ToList().ForEach(c => dataRow.SetField(c.Key, c.Value));
return dataRow;
}))
{
dataTable.Rows.Add(row);
}
return dataTable;
}
回答by philx_x
try my solution, seems very clean to me:
尝试我的解决方案,对我来说似乎很干净:
private DataTable DictonarysToDataTable(List<Dictionary<string, int>> list)
{
DataTable table = new DataTable();
foreach (Dictionary<string,string> dict in list) //for every dictonary in the list ..
{
foreach (KeyValuePair<string,int> entry in dict) //for every entry in every dict
{
if (!myTable.Columns.Contains(entry.Key.ToString()))//if it doesn't exist yet
{
myTable.Columns.Add(entry.Key); //add all it's keys as columns to the table
}
}
table.Rows.Add(dict.Values.ToArray()); //add the the Values of every dict in the list as a new row
}
return table;
}
Edit: Oh Snap, this works only for one Dictionary .. i didn't think it through. But maybie you can modify it to work for a List of Dictionarys ..
编辑:哦 Snap,这仅适用于一个字典......我没有考虑清楚。但是也许你可以修改它以适用于字典列表..
回答by Deathstalker
Give this a try please
请试一试
DataTable table = new DataTable();
foreach (IDictionary<string, object> row in DeviceTypeReport)
{
foreach (KeyValuePair<string, object> entry in row)
{
if (!table.Columns.Contains(entry.Key.ToString()))
{
table.Columns.Add(entry.Key);
}
}
table.Rows.Add(row.Values.ToArray());
}
回答by mehrab habibi
private DataTable toDataTable(List<RetirementDiskModelDto> retirementDiskModelDtos)
{
DataTable result = new DataTable();
foreach (var col in retirementDiskModelDtos.FirstOrDefault().Items)
result.Columns.Add(col.Key);
foreach (var row in retirementDiskModelDtos)
{
DataRow newrow = result.NewRow();
foreach (var col in retirementDiskModelDtos.FirstOrDefault().Items)
newrow[col.Key] = col.Value;
result.Rows.Add(newrow);
}
return result;
}