Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coverting List of Dictionary to DataTable

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

like image 284
Simsons Avatar asked Mar 08 '13 12:03

Simsons


3 Answers

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
like image 34
John Kraft Avatar answered Oct 31 '22 19:10

John Kraft


Try this

List<Dictionary<string, object>> ListDic;

var stringListDic = JsonConvert.SerializeObject(ListDic);

var dataTable = JsonConvert.DeserializeObject<DataTable>(stringListDic);
like image 123
liem xuan Avatar answered Oct 31 '22 17:10

liem xuan


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;
}
like image 7
Nikola Radosavljević Avatar answered Oct 31 '22 17:10

Nikola Radosavljević