【问题标题】:Filter an hierarchy list and keep the path过滤层次结构列表并保留路径
【发布时间】:2015-10-15 15:04:36
【问题描述】:

在 C# 中,我如何搜索层次结构列表并在最后保持路径完整。例如:

对象

public class Node
{
    public IEnumerable<Node> Children { get; set; }

    public string Id { get; set; }
}  

结果

  • 一个
    • aa
      • aaa
      • aab
  • b
    • bb
      • bba

我想要什么

如果我在这个列表中搜索“aab”这个词,我想向客户展示这个结果:

  • 一个
    • aa
      • aab

我发现搜索层次结构列表的一个实现是在https://stackoverflow.com/a/30907231/316759 那里采取的这个实现,但问题是它只返回找到的叶节点而不保留层次结构。

public static T DepthFirstSearch<T, TChilds>(this T node, Func<T, TChilds> ChildsProperty, Predicate<T> Match) where T : class
{
    Stack<T> stack = new Stack<T>();
    stack.Push(node);

    while (stack.Count > 0)
    {
        T thisNode = stack.Pop();

        if (Match(thisNode))
        {
            return thisNode;
        }

        if (ChildsProperty(thisNode) != null)
        {
            foreach (T child in (ChildsProperty(thisNode) as IEnumerable<T>).Reverse())
            {
                stack.Push(child);
            }
        }
    }

    return null;
}

我需要的是找到叶子节点并将它们的父节点保持在根节点。

【问题讨论】:

  • LINQ 树搜索到底有什么问题?有代码吗?
  • “DFS 和保持路径”是非常标准的面试问题。目前尚不清楚您有什么问题以及您希望有人为您编写什么样的解决方案(可能使用 SlectMany 的一行 LINQ 太复杂,递归也不好玩)......
  • @Vlad,他们只找到节点并将结果展平而不保留层次结构。
  • @AlexeiLevenkov,我已经更新了我的问题。我还尝试搜索有关 DFS 的更多信息,但我没有找到任何保留根路径的示例。
  • @AlexandreJobin 我认为您的代码对于初始尝试来说过于优化了...基本递归 DFS 更容易从中获取路径(请参阅我的帖子中的近似代码)。在您的代码中,您要么将(父、子)对保留在堆栈中,要么让“Node.Parent”收集返回路径。

标签: c# hierarchy depth-first-search


【解决方案1】:

这是一个快速示例,可让您标记所需的节点,如图所示:

public bool NodeOrChildrenMatch(Node n)
{
    if (IsMatch(n))
    {
        Show(n);
        return true;
    }
    else
    {
        if (n.Children.Any(NodeOrChildrenMatch))
        {
            Show(n);
            return true;
        }
        return false;
    }
}

【讨论】:

    【解决方案2】:

    近似代码 - 在递归下降时收集“路径”并在上升时清理最后一个元素:

    Stack<T> path = new Stack<T>();
    public static bool DepthFirstSearch(T node, Stack<T> path, Predicate<T> Match) 
    {
        path.Push(node);
    
        if (Match(node))
            return true;
    
        foreach (T child in (thisNode.Children)
        {
             if (DepthFirstSearch(child, stack, Match))
                  return true;
        }
    
        stack.Pop();
        return false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多