【问题标题】:Find maximum depth/level of a nested collection查找嵌套集合的最大深度/级别
【发布时间】:2013-08-22 01:46:29
【问题描述】:

我想创建一个可以找到嵌套树结构深度的属性。下面的静态通过递归找出深度/级别。但是是否可以将此函数作为同一个类中的属性而不是静态方法?

public static int GetDepth(MenuGroup contextMenuItems)
{
    if (contextMenuItems == null || contextMenuItems.Items.Count == 0)
        return 0;

    var subMenu = contextMenuItems.Items.Select(b => b as MenuGroup);
    if (!subMenu.Any())
        return 1;

    var subLevel = subMenu.Cast<MenuGroup>().Select(GetDepth);
    return !subLevel.Any() ? 1 : subLevel.Max() + 1;
}

有关代码的更多信息: MenuGroupMenuItem 派生自 MenuBase

MenuGroup 具有以ObservableCollection&lt;MenuBase&gt; Items 作为子元素的子节点

MenuItem 是一个没有任何子节点的离开节点。

【问题讨论】:

  • 您可以像这样创建属性:public int Depth {get {return GetDepth(something);} private set;} 就是那个 MenuGroup。您可以将方法设为私有和非静态,并在此方法中使用this

标签: c# linq recursion tree


【解决方案1】:

嗯,你可以很容易地把它变成一个实例属性,是的:

public int Depth
{
    get
    {
        if (Items.Count == 0)
            return 0;
        var subMenu = Items.Select(b => b as MenuGroup);
        if (!subMenu.Any())
            return 1;
        var subLevel = subMenu.Cast<MenuGroup>().Select(x = > x.Depth);
        return !subLevel.Any() ? 1 : subLevel.Max() + 1;
    }
}

由于处理非MenuGroup 项目,这还不会完全工作,但它可以很容易地修复,使用OfType 而不是Select 然后@987654325 @:

public int Depth
{
    get
    {
        // Completely empty menu (not even any straight items). 0 depth.
        if (Items.Count == 0)
        {
            return 0;
        }
        // We've either got items (which would give us a depth of 1) or
        // items and groups, so find the maximum depth of any subgroups,
        // and add 1.
        return Items.OfType<MenuGroup>()
                    .Select(x => x.Depth)
                    .DefaultIfEmpty() // 0 if we have no subgroups
                    .Max() + 1;
    }
}

【讨论】:

  • @defaultlocale:事实上,这并不是相当不必要的。我花了一段时间才弄清楚发生了什么,但我想我现在明白了。 OfType 当然更干净,我同意 - 请参阅我编辑的答案。
【解决方案2】:
public string GenerateMenu()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("<nav id=\"nvMenu\" class=\"main-nav\"><ul>");
    sb.Append(PrepareMenuUL(AppConfig._AppConfigInstance.Navigation.FirstOrDefault().NavigationClass));
    sb.Append("</ul></nav>");
    return sb.ToString();
}

private string PrepareMenuUL(List<Navigation> navigation)
{
    StringBuilder sb = new StringBuilder();

    if (Liflag == 1)
    {
        sb.Append("</li>");
        Liflag = 0;
    }

    foreach (var item in navigation)
    {
        var subMenu = item.NavigationClass.Select(b => b as Navigation);

        if (subMenu.Any())
        {
            sb.Append("<li class=\"dropdown\">");
            if (subMenu.Any() && item.Url == "#")
                sb.Append(string.Format("<a href=\"{0}\">{1}<i class=\"icon-arrow\"></i></a>", BaseUrl + item.Url, item.Name));
            else if (subMenu.Any() && item.Url != "#" && item.Url != null)
                sb.Append(string.Format("<a href=\"{0}\">{1}<i class=\"icon-rightarrow\"></i></a>", BaseUrl + item.Url, item.Name));
        }
        else
        {
            sb.Append("<li>");
            sb.Append(string.Format("<a href=\"{0}\">{1}</a>", BaseUrl + item.Url, item.Name));
        }

        if (subMenu.Any())
            sb.Append("<ul class=\"wd190\">");

        if (item.NavigationClass.Count > 0)
        {
            Liflag = 1;
            sb.Append(PrepareMenuUL(item.NavigationClass));
        }

        sb.Append("</li>");

        if (subMenu.Any())
            sb.Append("</ul>");
    }

    return sb.ToString();
}

【讨论】:

  • 您可以通过用户递归来找到列表的深度。在上面显示的方式
猜你喜欢
  • 2011-08-27
  • 1970-01-01
  • 2018-04-14
  • 2020-12-10
  • 2018-12-13
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 2022-10-16
相关资源
最近更新 更多