如何为嵌套集合编写Linq或Lambda表达式

时间:2015-05-05 03:04:45

标签: c# linq lambda nested

我知道简单的linq,但这里的问题陈述有多层次的嵌套。如何为嵌套集合编写Linq或Lambda表达式。

输入对象定义:

public class Service
{
    public string Name { get; set; }
    public List<Service> ChildServices{ get; set; }

    public List<Action> AvailableActions{ get; set; }
}

public class Action
{
    public string Name { get; set; }
    public List<string> Parameters{ get; set; }

    public void Execute()
    {
        ...
    }
}

嵌套可以转到多个级别

Linq预期输出

这里我需要编写Linq或Lambda表达式

  1. 获取所有服务
  2. 获取具有指定名称的服务

2 个答案:

答案 0 :(得分:1)

如果我们可以假设您从一系列服务开始,例如:

var services = new List<Service>()
{
    new Service()
    {
        Name = "A",
        ChildServices = new List<Service>()
        {
            new Service() { Name = "C", ChildServices = new List<Service>() },
            new Service()
            {
                Name = "D",
                ChildServices = new List<Service>()
                {
                    new Service() { Name = "E", ChildServices = new List<Service>() },
                    new Service() { Name = "F", ChildServices = new List<Service>() },
                }
            },
        }
    },
    new Service()
    {
        Name = "B",
        ChildServices = new List<Service>()
        {
            new Service() { Name = "G", ChildServices = new List<Service>() },
            new Service() { Name = "H", ChildServices = new List<Service>() },
        }
    },
};

看起来像这样:

services

然后这个查询会将列表展平:

Func<IEnumerable<Service>, IEnumerable<Service>> traverse = null;
traverse = ss =>
    from s in ss
    from s2 in new [] { s }.Concat(traverse(s.ChildServices))
    select s2;

调用traverse(services)会返回此信息:

flattened

然后,您可以使用普通的LINQ查询按名称查找服务,或者您可以创建这样的字典:

var serviceByName = traverse(services).ToDictionary(x => x.Name);

var serviceG = serviceByName["G"];

答案 1 :(得分:0)

我认为没有直接的方式来递归查询嵌套集合(Atleast I&#39; m)。

以下解决方案可能适用于您的案例。

public class Service
{
    public string Name { get; set; }
    public List<Service> ChildServices{ get; set; }

    public List<Action> AvailableActions{ get; set; }
}

public class Action
{
    public string Name { get; set; }
    public List<string> Parameters{ get; set; }

    public void Execute()
    {

    }
}

public static class Extensions
{
    public static IEnumerable<Service> GetAllServices(this Service node)
    {
        yield return node;
        if(node.ChildServices != null)
        {
            foreach(var child in node.ChildServices)
            {
                foreach(var childOrDescendant in child.GetAllServices())
                {
                    yield return childOrDescendant;
                }
            }
        }
    }
}

工作小提琴手Sample