将字典列表转换为数据表

本文关键字:数据表 转换 列表 字典 | 更新日期: 2023-09-27 18:02:51

目前我们是通过循环遍历list和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;
       }

但是有更好的方法吗?循环这么多次感觉不太好

将字典列表转换为数据表

上面的答案没有解决字典有多于一行的问题。这个解决方案解决了这个问题。

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();
}

输出如下…

a       b       c       bob     tom     Yip Yip Yap Yap
1       2       3
                        34      37
                                        8       9

速度、优雅和可重用性不能同时存在。你总是选择更重要的一个,并试图平衡其他两个。

代码越快,越丑。它越漂亮,可重用性越低。

这是一个"优雅"的解决方案的例子,但是它不是很好读。

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;
}

试试这个

List<Dictionary<string, object>> ListDic;
var stringListDic = JsonConvert.SerializeObject(ListDic);
var dataTable = JsonConvert.DeserializeObject<DataTable>(stringListDic);

试试这个:

    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;
    }

像下面这样的代码怎么样?

很好,因为它只迭代每一行一次。它应该是相当快的,我已经包含了明显的异常,使代码更安全。

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;
    }
} 

试试我的解决方案,对我来说似乎很干净:

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;
    }

编辑:哦,呸,这只适用于一本字典…我没有想清楚。但也许你可以修改它,使其适用于字典列表。

请尝试一下

        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());
        }
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;
        }