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

          };

var pivotTable1 = data.ToPivotTable(item => item.Year, item => item.Product, items => items.Any() ? items.Sum(x => x.Sales) : 0);

jsonStr = JsonConvert.SerializeObject(pivotTable);


//行转列

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

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;

        }

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

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;

}

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐