【问题标题】:Coverting List of Dictionary to DataTable将字典列表转换为数据表
【发布时间】:2020-12-11 11:33:51
【问题描述】:

目前我们通过遍历列表和字典的每个值来做到这一点:

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;

       }

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

【问题讨论】:

  • 像什么?任何其他方法最终都需要检查您的所有数据 c.q.循环遍历记录。我没有看到你遇到的真正问题。你不喜欢上面的代码?
  • 这行得通,但如前所述,有没有更好、更强大的方法
  • 为什么首先要转换成DataTable?
  • @Jodrell,因为 DataTable can 在 Seilverlight 中不存在,有时从服务返回时无法序列化
  • 你想达到什么目的?速度更快?代码的可重用性?代码优雅?对于初学者,不要在List&lt;T&gt; 上使用Count() 扩展方法。请改用Count 属性。

标签: c# .net casting datatable


【解决方案1】:

上面的答案没有解决字典超过 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();

}

输出看起来像......

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

【讨论】:

  • 您的输出与您的输入不匹配。
  • (捂脸)哎呀。你说的对。我不小心使用了错误的迭代器。已更正。
  • 这样可以节省时间。赞一个!
  • 填充您云的数据表的列也使用: foreach (KeyValuePair entry in myDictonary) { myTable.Columns.Add(entry.Key); }
【解决方案2】:

速度、优雅和可重用性不能并存。您总是选择更重要的一项,并尝试平衡其他两项。

代码越快,越难看。 它更漂亮,可重用性更低。

这是一个“优雅”解决方案的示例,但它的可读性并不高。

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】:

试试这个

List<Dictionary<string, object>> ListDic;

var stringListDic = JsonConvert.SerializeObject(ListDic);

var dataTable = JsonConvert.DeserializeObject<DataTable>(stringListDic);

【讨论】:

    【解决方案4】:

    试试这个:

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

    【讨论】:

      【解决方案5】:

      下面的代码怎么样?

      很好,因为它只对每一行迭代一次。它应该很快,我已经包含了明显的例外以使代码更安全。

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

      【讨论】:

      • 你没有处理枚举数。
      【解决方案6】:

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

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

      编辑: 哦,Snap,这仅适用于一个字典..我没有考虑清楚。 但也许你可以修改它以适用于字典列表..

      【讨论】:

        【解决方案7】:

        请尝试一下

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

        【讨论】:

          【解决方案8】:
          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;
                  }
          

          【讨论】:

            猜你喜欢
            • 2017-04-23
            • 2021-10-13
            • 1970-01-01
            • 2015-07-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多