C# 行列互转 List<T>、DataTable和匿名对象 行转列 返回

C#论坛 老数据
4785

用LINQ把列转换成行

 在这篇文章中,我们将做同样的事情,但是使用c#的数组和数据表,使用LINQ或Lambda表达式的力量

C# 数组集合或者List<T> 行转列到 DataTable

这里是C#对象

var data = new[] {
              new { Product = "Product 1", Year = 2009, Sales = 1212 },
              new { Product = "Product 2", Year = 2009, Sales = 522 },
              new { Product = "Product 1", Year = 2010, Sales = 1337 },
              new { Product = "Product 2", Year = 2011, Sales = 711 },
              new { Product = "Product 2", Year = 2012, Sales = 2245 },
              new { Product = "Product 3", Year = 2012, Sales = 1000 }
          };


下面是我们定义的扩展方法

public static DataTable ToPivotTable<T, TColumn, TRow, TData>(
    this IEnumerable<T> source,
    Func<T, TColumn> columnSelector,
    Expression<Func<T, TRow>> rowSelector,
    Func<IEnumerable<T>, TData> dataSelector)
        {
            DataTable table = new DataTable();
            var rowName = ((MemberExpression)rowSelector.Body).Member.Name;
            table.Columns.Add(new DataColumn(rowName));
            var columns = source.Select(columnSelector).Distinct();
 
            foreach (var column in columns)
                table.Columns.Add(new DataColumn(column.ToString()));
 
            var rows = source.GroupBy(rowSelector.Compile())
                             .Select(rowGroup => new
                             {
                                 Key = rowGroup.Key,
                                 Values = columns.GroupJoin(
                                     rowGroup,
                                     c => c,
                                     r => columnSelector(r),
                                     (c, columnGroup) => dataSelector(columnGroup))
                             });
 
            foreach (var row in rows)
            {
                var dataRow = table.NewRow();
                var items = row.Values.Cast<object>().ToList();
                items.Insert(0, row.Key);
                dataRow.ItemArray = items.ToArray();
                table.Rows.Add(dataRow);
            }
 
            return table;
        }


您可以为扩展方法创建一个静态类并将其放在那里。
要将年份值转换为列并获取数据透视表:


You will get the following output:

C# 将List<T>集合行转列到匿名对象集合

 在将列转换为行之后,您可能希望获得List<dynamic>或dynamic[],而不是获得DataTable。它在ASP中很方便。NET Web API返回JSON响应。
为此,我更新了扩展方法以获得动态对象。使用以下扩展方法:
吗?

public static List<dynamic>  ToPivotArray<T, TColumn, TRow, TData>(
this IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
       {
 
           var arr = new List<object>();
           var cols = new List<string>();
           String rowName = ((MemberExpression)rowSelector.Body).Member.Name;
           var columns = source.Select(columnSelector).Distinct();      
 
           cols =(new []{ rowName}).Concat(columns.Select(x=>x.ToString())).ToList();
  
           var rows = source.GroupBy(rowSelector.Compile())
                            .Select(rowGroup => new
                            {
                                Key = rowGroup.Key,
                                Values = columns.GroupJoin(
                                    rowGroup,
                                    c => c,
                                    r => columnSelector(r),
                                    (c, columnGroup) => dataSelector(columnGroup))
                            }).ToArray();
  
           foreach (var row in rows)
           {
               var items = row.Values.Cast<object>().ToList();
               items.Insert(0, row.Key);
               var obj = GetAnonymousObject(cols, items);
               arr.Add(obj);              
           }
           return arr.List();
       }
 private static dynamic GetAnonymousObject(IEnumerable<string> columns, IEnumerable<object> values)
       {
           IDictionary<string, object> eo = new ExpandoObject() as IDictionary<string, object>;
           int i;
           for (i = 0; i < columns.Count(); i++)
           {
               eo.Add(columns.ElementAt<string>(i), values.ElementAt<object>(i));
           }
           return eo;
       }


ExpandoObject用于创建动态对象

现在,要将行转换为列并获得动态数组

C# 将Datatable行转列成Datatable

让我们有一个带有相同数据的数据表

DataTable myDataTable = new DataTable();
myDataTable.Columns.AddRange(new DataColumn[3] { new DataColumn("Product"), 
new DataColumn("Year", typeof(int)), new DataColumn("Sales", typeof(int)) });
myDataTable.Rows.Add("Product 1", 2009, 1212);
myDataTable.Rows.Add("Product 2", 2009, 522);
myDataTable.Rows.Add("Product 1", 2010, 1337);
myDataTable.Rows.Add("Product 2", 2011, 711);
myDataTable.Rows.Add("Product 2", 2012, 2245);
myDataTable.Rows.Add("Product 3", 2012, 1000);


您可以使用相同的扩展方法来获取如下所示的行转列的 DataTable。

DataTable to List<dynamic>:

如果你需要将DataTable转换为List of dynamic object,那么使用以下扩展方法:

public static List<dynamic> ToDynamicList(this DataTable dt)
{
           var list = new List<dynamic>();
           foreach (DataRow row in dt.Rows)
           {
               dynamic dyn = new ExpandoObject();
               list.Add(dyn);
               foreach (DataColumn column in dt.Columns)
               {
                   var dic = (IDictionary<string, object>)dyn;
                   dic[column.ColumnName] = row[column];
               }
           }
           return list;
}


这儿是结果:

总结:

在这篇文章中,我们使用了c#数组,数据表,实现了行到列的转换,并获得动态对象的数据透视数组,数据表和列表。


热忱回答0