2013-03-08 5 views
7

Derzeit tun wir dies, indem sie durch jeden Wert der Liste und Wörterbuch Looping:coverting Liste der Wörterbuch zu Datatable

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; 

     } 

Aber gibt es einen besseren Weg? Schleifen so oft fühlt sich nicht gut an

+0

Was zum Beispiel? Jeder andere Ansatz müsste schließlich alle Ihre Daten c.q. Schleife über die Datensätze. Ich sehe nicht das wirkliche Problem, das Sie haben. Sie mögen den obigen Code nicht? – Bazzz

+0

Das funktioniert, aber wie gesagt gibt es einen besseren, robusten Weg – Simsons

+3

Warum in eine DataTable überhaupt konvertieren? – Jodrell

Antwort

4

Geschwindigkeit, Eleganz und Wiederverwendbarkeit gehen nicht zusammen. Sie wählen immer wichtigere und versuchen, die anderen beiden auszugleichen.

Schneller der Code, hässlicher ist es. Schöner ist es, weniger wiederverwendbar ist es.

Hier ist ein Beispiel für "elegante" Lösung, aber das ist damit nicht gut lesbar.

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

iterieren Sie die erste Zeile zweimal. – Jodrell

+0

und "int" ist bereits ein "Objekt" – Jodrell

+0

Es gibt keine feste Beziehung zwischen Leistung und Lesbarkeit. Schneller Code kann lesbarer Code sein. Hässlichkeit ist rein subjektiv. – Jodrell

1

Wie wäre es mit etwas wie dem Code unten?

Gut, weil es jede Zeile genau einmal iteriert. Es sollte ziemlich schnell sein, ich habe offensichtliche Ausnahmen eingefügt, um den Code sicherer zu machen.

+0

Sie entsorgen den Enumerator nicht. – Romoku

+0

@Romoku, wahr, reparierte es. – Jodrell

8

Die obigen Antworten beziehen sich nicht auf das Problem des Wörterbuchs mit mehr als 1 Zeile. Diese Lösung behebt das Problem.

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

} 

Und die Ausgabe sieht aus wie ...

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

Ihre Ausgabe stimmt nicht mit Ihrer Eingabe überein. – Jodrell

+1

(facepalm) oops. Du hast recht. Ich habe versehentlich den falschen Iterator verwendet. Mit Korrektur bearbeitet. –

+0

Dies war eine Zeitersparnis. Kudos! –

1

Versuchen Sie folgendes:

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

meine Lösung versuchen, mir sehr sauber scheint:

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

bearbeiten : Oh Snap, das funktioniert nur für ein Dicti onary .. ich habe es nicht durchdacht. Aber maybie Sie ändern können, es für eine Liste des Dictionarys .. arbeiten

0

Geben Sie diesen einen Versuch bitte

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