12

現在、リストと辞書の各値をループすることでこれを行っています。

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;

       }

しかし、より良い方法はありますか?何度もループするのは気分が悪い

4

8 に答える 8

19

上記の回答は、辞書に複数の行があるという問題に対処していません。このソリューションは、この問題に対処します。

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
于 2013-03-08T14:57:20.337 に答える
7

スピード、エレガンス、再利用性は両立しません。常により重要なものを選択し、他の 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;
}
于 2013-03-08T12:47:14.650 に答える
1

以下のコードのようなものはいかがですか?

各行を正確に 1 回反復するためです。コードをより安全にするために、明らかな例外を含めました。

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;
    }
} 
于 2013-03-08T12:51:24.900 に答える
1

これを試して:

    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;
    }
于 2013-03-08T14:59:03.383 に答える
0

これを試してみてください

        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());
        }
于 2016-08-31T21:56:14.257 に答える