Linq分组和嵌套分组

时间:2015-03-11 21:33:36

标签: c# linq aggregate-functions

我正在创建可以使用各种分组显示的TreeView。基本课程如下:

public class MachineStatus 
{
  public string MachineName {get;set;} 
  public string Department {get;set;}
  public string LocationName {get;set;}
  public IEnumerable<DeviceStatus> Devices {get;set;}
}

public class DeviceStatus
{
  public string DeviceName {get;set;}
  public string DeviceType {get;set;}
  public string IpAddress {get;set;}
  public ConnectionStatus Status {get;set;}
}

这些群组可以是DepartmentLocationDeviceType。 Linq很容易前两个。但是,DeviceType具有挑战性,因为每个Machine可能包含多个具有不同类型的Device个对象。

原始数据

Machine 1
  |__ Device A (Type Foo)
  |__ Device B (Type Bar)
Machine 2
  |__ Device C (Type Foo)
  |__ Device D (Type Zed)

结果

Type Bar
  |__ Machine 1
      |__Device B
Type Foo
  |__Machine 1
      |__Device A
  |__Machine 2
      |__Device C
Type Zed
  |__Machine 2
      |__Device D

我认为在尝试分组之前我必须将MachineStatus记录列表展平,但我在使用SelectMany时感到困惑......

2 个答案:

答案 0 :(得分:1)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsoleApp
{
class Program
{
    static void Main(string[] args) {
        DeviceStatus deviceA = new DeviceStatus() { DeviceName = "A", DeviceType = "foo" };
        DeviceStatus deviceB = new DeviceStatus() { DeviceName = "B", DeviceType = "bar" };
        DeviceStatus deviceC = new DeviceStatus() { DeviceName = "C", DeviceType = "foo" };
        DeviceStatus deviceD = new DeviceStatus() { DeviceName = "D", DeviceType = "zed" };


        MachineStatus status1 = new MachineStatus() { MachineName = "1", Department = "1", LocationName = "1", Devices = new List<DeviceStatus>{ deviceA, deviceB} };
        MachineStatus status2 = new MachineStatus() { MachineName = "2", Department = "2", LocationName = "2", Devices = new List<DeviceStatus> { deviceC, deviceD } };

        List<MachineStatus> machines = new List<MachineStatus>() { status1, status2};

        var result = machines.SelectMany(x => x.Devices, (a, b) => new { DeviceType = b.DeviceType, MachineName = a.MachineName, DeviceName = b.DeviceName } );
        var result2 = result.GroupBy(x => new {x.DeviceType}).Select( z => new { DeviceType = z.Key.DeviceType, Machines = z.ToList().GroupBy(y => y.MachineName) });

        foreach (var group1 in result2)
        {
            foreach (var group2 in group1.Machines)
            {
                foreach (var group3 in group2)
                {
                    Console.Write(group1.DeviceType + ":");
                    Console.Write(group3.MachineName + ":");
                    Console.WriteLine(group3.DeviceName);
                }
            }
        }

        Console.ReadLine();

    }

    public class MachineStatus
    {
        public string MachineName { get; set; }
        public string Department { get; set; }
        public string LocationName { get; set; }
        public IEnumerable<DeviceStatus> Devices { get; set; }
    }

    public class DeviceStatus
    {
        public string DeviceName { get; set; }
        public string DeviceType { get; set; }
        public string IpAddress { get; set; }
        public ConnectionStatus Status { get; set; }
    }

    public class ConnectionStatus
    {
    }
}
}

产生以下输出:

FOO:1:甲
FOO:2:C
条:1:乙
zed:2:D

分组为:

FOO:1:甲
foo:2:C

吧:1:B

zed:2:D

答案 1 :(得分:1)

您可以使用SelectMany&amp; GroupBy是这样的: -

var result = machines.SelectMany(x => x.Devices, 
                                    (machineObj, devices) => new { machineObj, devices })
                     .GroupBy(x => new { x.devices.DeviceType, x.machineObj.Department, 
                                                             x.machineObj.LocationName })
                     .Select(x => new
                                 {
                                     DeviceType = x.Key.DeviceType,
                                     Department = x.Key.Department,
                                     Location = x.Key.LocationName,
                                     machines = x
                                 });

以下是我用过的样本数据的完整Working Fiddle,以下是同样的输出。

enter image description here