递归搜索分层列表

发布于 2024-10-03 06:44:57 字数 1922 浏览 1 评论 0原文

我有一个对象的分层列表。假设结构如下:

  • 根节点
    • 父节点
      • 子节点
    • 父节点
      • 子节点
    • 父节点
      • 子节点

子节点可以有自己的子节点,但目标是基本上搜索“父节点”。因此,假设父节点类有一个名为“Name”的属性 - 并且用户输入部分名称,我希望返回名称包含用户搜索条件的所有父节点。基本上,这更像是一个“过滤”功能。所以,我知道如何做到这一点,但是,我遇到的问题是他们的关键目标是保持层次结构完整。换句话说,如果有一个父节点符合过滤条件,我希望返回以下结构:

  • 根节点
    • 父节点
      • 子节点

我目前的努力仅产生:

  • 父节点
    • 子节点

我正在使用 Linq。任何建议将不胜感激。

谢谢!

Chris

当前过滤器实现的代码片段如下:

FilteredReports = Reports.FirstOrDefault().Children.Cast<IHierarchicalResult>()
                                    .SelectRecursive(item => item.Children.Cast<IHierarchicalResult>())
                                    .Where(item => item.Name.ToLower().StartsWith(filterCriteria))
                                    .ToObservableCollection();

这是我正在使用的扩展方法:

public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
    {
        if (null == source)
        {
            throw new ArgumentNullException("source");
        }

        if (null == getChildren) return source;

        return SelectRecursiveIterator(source, getChildren);
    }

    private static IEnumerable<T> SelectRecursiveIterator<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
    {
        foreach (T item in source)
        {
            yield return item;

            IEnumerable<T> children = getChildren(item);
            if (null != children)
            {
                foreach (T child in SelectRecursiveIterator(children, getChildren))
                {
                    yield return child;
                }
            }
        }
    }

I have a hierarchical list of objects. Assume that the structure is as follows:

  • Root node
    • Parent node
      • child node
    • Parent node
      • child node
    • Parent node
      • child node

The child nodes could have their own children, but the objective is to basically search the "parent nodes". So, let's say that the parent node class has a property called "Name" - and the user enters a partial name, I want all of the parent nodes whose name contains the user's search criteria to be returned. Basically, this is more of a "filter" functionality than anything. So, I know how to do this, however, the problem that I am running into is that they key objective is to keep the hierarchical structure in tact. In other words, if there is one parent node that matches the filter criteria, I want the structure below to be returned:

  • Root node
    • Parent node
      • child node

My current efforts only yield:

  • Parent node
    • child node

I am using Linq. Any suggestions would be greatly appreciated.

Thanks!

Chris

Code snippet below for current filter implementation:

FilteredReports = Reports.FirstOrDefault().Children.Cast<IHierarchicalResult>()
                                    .SelectRecursive(item => item.Children.Cast<IHierarchicalResult>())
                                    .Where(item => item.Name.ToLower().StartsWith(filterCriteria))
                                    .ToObservableCollection();

Here is the extension method I am using:

public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
    {
        if (null == source)
        {
            throw new ArgumentNullException("source");
        }

        if (null == getChildren) return source;

        return SelectRecursiveIterator(source, getChildren);
    }

    private static IEnumerable<T> SelectRecursiveIterator<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
    {
        foreach (T item in source)
        {
            yield return item;

            IEnumerable<T> children = getChildren(item);
            if (null != children)
            {
                foreach (T child in SelectRecursiveIterator(children, getChildren))
                {
                    yield return child;
                }
            }
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

山有枢 2024-10-10 06:44:57

由于您想要返回的根节点与原始根节点不同(它的子节点较少),因此您需要创建一个仅包含匹配的子节点的新根节点。

像这样的东西

  Node oldRootNode = ...
  List<Node> filteredChildren = oldRootNode.Children.Where(...).ToList();
  Node newRootNode = new Node {Name = oldRootNode.Name, Children = filteredChildren};

  return newRootNode;

Since the Root node you want returned is NOT the same as the original root node (it has less children) you'll need to create a new root node containing just the children that match.

Something like

  Node oldRootNode = ...
  List<Node> filteredChildren = oldRootNode.Children.Where(...).ToList();
  Node newRootNode = new Node {Name = oldRootNode.Name, Children = filteredChildren};

  return newRootNode;
一杆小烟枪 2024-10-10 06:44:57

您可以在这里做一些事情。

  1. 您可以创建主结构的副本并从过滤器中返回它(尽可能浅复制,但您必须深层复制节点之间的链接)
  2. 您可以扩展节点以了解它们是否已被过滤(即 IsFilteredOut、ChildrenUnfilteredGet() 等),然后显示“过滤”树。
  3. 您可以存储过滤节点的列表(黑名单或白名单),然后在显示树时引用该列表(这涉及最少的代码更改,但处理能力最强)。

There are a few things you can do here.

  1. You can create a copy of the main structure and return it from your filter (shallow copying as much as possible, but you'll have to deep copy the links between nodes)
  2. You can extend your nodes to understand whether or not they've been filtered (i.e. IsFilteredOut, ChildrenUnfilteredGet(), etc.) and then display the "filtered" tree.
  3. You can store a list of filtered nodes (blacklist or whitelist) and then refer to that when displaying the tree (this involves the fewest code changes but the most processing power).
猫性小仙女 2024-10-10 06:44:57

根据记忆(可能包含拼写错误)并且基于不知道您的代码:

var filteredList = myRootNode.CollectionOfParentNodes.Where(p => p.Name.Contains(searchCriteriaString)).ToList();

From memory (may contain typos) and based on not knowing your code:

var filteredList = myRootNode.CollectionOfParentNodes.Where(p => p.Name.Contains(searchCriteriaString)).ToList();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文