使用Linq </t>在两个嵌套的List <t>中透视数据

时间:2015-03-30 10:58:15

标签: c# linq pivot-table

我有以下类结构:

class Employee()
{
  public String Name { get; set; }
  public List<WorkDay> WorkDays { get; set; }
}

class WorkDay()
{
  public DateTime Date { get; set; }
  public Int Hours { get; set; }
}

是否可以使用Linq来转移List<Employee>,所以我的DataGridView中有这样的结果:

           | Name    | Name    |...| Name      |
Date       | Hours   | Hours   |   | Hours     |
Date       | Hours   | Hours   |   | Hours     |   
Date       | Hours   | Hours   |   | Hours     |
Date       | Hours   | Hours   |   | Hours     |
...        | Hours   | Hours   |   | Hours     |

这很棘手,因为它是两个嵌套列表,我只找到了单个列表的例子,非常简单。 Is it possible to Pivot data using LINQ?

我已经达到了这一点,但它还没有完全存在:

var _result = Employees.SelectMany(x => x.WorkDays)
                       .GroupBy(x => x.Date)
                       .Select(y => new
                                    {
                                        DATE = y.Key,
                                        NAME = y.Select(z => z.Employee.Name).ToArray()
                                    })
                       .ToList();

我很感激任何建议。

2 个答案:

答案 0 :(得分:1)

我认为你需要这个: -

var result = employees.SelectMany(x => x.WorkDays, (employeeObj, workDays) => 
                                                   new { employeeObj, workDays })
                      .GroupBy(x => x.workDays.Date)
                      .Select(x => new
                             {
                                Date = x.Key,
                                NameAndHours = x.Select(z => 
                                    new { 
                                            Name = z.employeeObj.Name, 
                                            Hours = z.workDays.Hours 
                                        })
                             }).ToList();

以下是包含一些示例数据的Working Fiddle

答案 1 :(得分:1)

此示例使用WPF,但您可以使用方法&#34; PivotWorkingHours&#34;对于Winforms或Webforms也是......

输出:

enter image description here

窗口:

<Window x:Class="WpfApplication5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid Name="pivotTarget" ItemsSource="{Binding}"/>
    </Grid>
</Window>

实现:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        List<Employee> demo = new List<Employee>
                              {
                                  new Employee{Name = "Frank", WorkDays = new List<WorkDay>
                                                                        {
                                                                            new WorkDay{Date = new DateTime(2001,1,2), Hours = 8},
                                                                            new WorkDay{Date = new DateTime(2001,1,3), Hours = 7},
                                                                        }},
                                  new Employee{Name = "Herbert", WorkDays = new List<WorkDay>
                                                                        {
                                                                            new WorkDay{Date = new DateTime(2001,1,2), Hours = 8},
                                                                            new WorkDay{Date = new DateTime(2001,1,4), Hours = 7},
                                                                        }}

                              };
        pivotTarget.DataContext = PivotWorkingHours(demo);

    }

    private DataTable PivotWorkingHours(IEnumerable<Employee> employees)
    {
        DataTable result = new DataTable();
        result.Columns.Add("Date", typeof(DateTime));
        foreach (string name in employees.Select(x => x.Name).Distinct())
        {
            result.Columns.Add(name, typeof(int));
        }
        foreach (DateTime date in employees.SelectMany(e => e.WorkDays.Select(wd => wd.Date)).Distinct())
        {
            DataRow row = result.NewRow();
            row["Date"] = date;
            foreach (Employee employee in employees)
            {
                row[employee.Name] = employee.WorkDays.Where(wd => wd.Date == date).Sum(wd => wd.Hours);
            }
            result.Rows.Add(row);
        }


        return result;
    }
}

class Employee
{
    public String Name { get; set; }
    public List<WorkDay> WorkDays { get; set; }
}

class WorkDay
{
    public DateTime Date { get; set; }
    public int Hours { get; set; }
}