【问题标题】:linq nested list containslinq 嵌套列表包含
【发布时间】:2012-09-07 12:42:43
【问题描述】:

我有一个问题要请教 linq 专家! 在 Component 实例的嵌套列表中,我需要知道其中是否存在特定类型的组件。可以用linq表达吗?考虑到可能有 application.Components[0].Components[0].Components[0]... 我的问题是针对 linq 中的递归查询!

我把实体留给你,让你对模型有一些了解。

public class Application
{
    public List<Component> Components { get; set; }
}

public class Component
{
    public ComponentType Type { get; set; }
    public List<Component> Components { get; set; }
}

public enum ComponentType
{
    WindowsService,
    WebApplication,
    WebService,
    ComponentGroup
}

【问题讨论】:

    标签: c# linq recursion tree nested-class


    【解决方案1】:

    您想知道组件中的任何组件是否属于给定类型?

    var webType = ComponentType.WebApplication;
    IEnumerable<Component> webApps = from c in components
                                     from innerComp in c.Components
                                     where innerComp.Type == webType;
    bool anyWebApp = webApps.Any();
    

    innercomp.components 呢?

    编辑:因此您希望递归地查找给定类型的组件,而不仅仅是在顶层或第二层。然后你可以使用下面的Traverse 扩展方法:

    public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
    {
        foreach (T item in source)
        {
            yield return item;
    
            IEnumerable<T> seqRecurse = fnRecurse(item);
            if (seqRecurse != null)
            {
                foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
                {
                    yield return itemRecurse;
                }
            }
        }
    }
    

    以这种方式使用:

    var webType = ComponentType.WebApplication;
    IEnumerable<Component> webApps = components.Traverse(c => c.Components)
                                     .Where(c => c.Type == webType);
    bool anyWebApp = webApps.Any();
    

    样本数据:

    var components = new List<Component>() { 
        new Component(){ Type=ComponentType.WebService,Components=null },
        new Component(){ Type=ComponentType.WebService,Components=new List<Component>(){
            new Component(){ Type=ComponentType.WebService,Components=null },
            new Component(){ Type=ComponentType.ComponentGroup,Components=null },
            new Component(){ Type=ComponentType.WindowsService,Components=null },
        } },
        new Component(){ Type=ComponentType.WebService,Components=null },
        new Component(){ Type=ComponentType.WebService,Components=new List<Component>(){
            new Component(){ Type=ComponentType.WebService,Components=new List<Component>(){
                new Component(){Type=ComponentType.WebApplication,Components=null}
            } },
            new Component(){ Type=ComponentType.WindowsService,Components=null },
            new Component(){ Type=ComponentType.WebService,Components=null },
        } },
        new Component(){ Type=ComponentType.WebService,Components=null },
        new Component(){ Type=ComponentType.ComponentGroup,Components=null },
        new Component(){ Type=ComponentType.WebService,Components=null },
    };
    

    【讨论】:

    • innercomp.components 怎么样?
    • @IrrationalRationalWorks:编辑了我的答案。
    • 我在吃彩虹......让我检查一下
    • 你是终极的linq、扩展方法、递归大师蒂姆!
    【解决方案2】:
    if( Components.Any( c => c.Type == ComponentType.WindowsService ) )
    {
       // do something
    }
    

    或者你可以这样做

    var listContainsAtLeastOneService = 
        ( from c in Components
          where c.Type == ComponentType.WindowsService
          select c ).Any( );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 2016-01-14
      • 2011-11-02
      • 1970-01-01
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      相关资源
      最近更新 更多