Coverting List of Dictionary to DataTable

橙三吉。 提交于 2019-12-21 09:33:48

问题


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


回答1:


The answers above don't address the issue of the dictionary having more than 1 row. This solution addresses the issue.

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



回答2:


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



回答3:


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



回答4:


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



回答5:


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 ..




回答6:


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



回答7:


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


来源:https://stackoverflow.com/questions/15293653/coverting-list-of-dictionary-to-datatable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!