用于反透视数据表的 Lambda 表达式

Lambda Expression for Unpivoting DataTable

我正在以下列格式从 Excel sheet 中读取数据:

我需要按以下方式存储数据:

我正在尝试借助 Linq lambda 表达式来完成此操作,但我认为我对此一无所获。

DataTable dataTable= ReadExcel();
var dt = dataTable.AsEnumerable();

var resultSet = dt.Where(x => !String.IsNullOrEmpty(x.Field<String>("Project_Code")))
                .GroupBy(x =>
                            new
                            {
                                Month = x.Field<String>("Month"),
                                ProjectCode = x.Field<String>("Project_Code"),
                                //change designation columns into row data and then group on it 
                                //Designation = 
                            }
                        );
                //.Select(p =>
                //            new
                //            {
                //                Month= p.d
                //            }
                //        );`

我会将 ToDictionary 与 pre-defined 组指定名称一起使用:

private static readonly string[] designationNames = {"PA","A","SA","M","SM","CON"};
void Function()
{
    /* ... */
    var resultSet = dt.AsEnumerable().Where(x => !String.IsNullOrEmpty(x.Field<String>("Project_Code")))
            .Select(x =>
                new
                {
                    Month = x.Field<String>("Month"),
                    ProjectCode = x.Field<String>("Project_Code"),
                    Designations = designationNames.ToDictionary(d => d, d => x.Field<int>(d))
                }
            );
}

这是标准化版本。如果你想让它变平,请使用:

private static readonly string[] designationNames = {"PA","A","SA","M","SM","CON"};

void Function()
{
    /* ... */
    var resultSet = dt.AsEnumerable().Where(x => !String.IsNullOrEmpty(x.Field<String>("Project_Code")))
        .Select(x =>
            designationNames.Select(
                d =>
                    new
                    {
                        Month = x.Field<String>("Month"),
                        ProjectCode = x.Field<String>("Project_Code"),
                        Designation = d,
                        Count = x.Field<int>(d)
                    }
            )
        ).SelectMany(x => x).ToList();
}

如果类型不总是 int 那么你可能想使用 x.Field<String>(d) 来代替并检查有效性。