在 IEnumerable 集合中查找所有依赖子项的最佳方法是什么

发布于 2024-09-09 21:35:44 字数 580 浏览 2 评论 0原文

我有一个包含 2 个表的数据库:

  1. Items
  2. ItemDependency

Items 的键为 ID

ItemDependency 有两列:ItemIdDependsOnItemId

我将其转换为集合:

 IEnumerable<Item> items = GetItems();

每个项目都有一个:依赖项属性,它是一个

List<Item>

所以我想将初始项目列表过滤为:

  1. 给定一个项目,我想要一个列表该项目以及递归依赖于该项目的所有项目。

  2. 给定一个项目,我想要该项目及其所依赖的所有其他项目的列表(也是递归地)。

在 C#、LINQ 或其他可以实现这一点的东西中,最好的方法是什么?

I have a database with 2 tables:

  1. Items
  2. ItemDependencies

Items has key of ID

ItemDependencies have two columns: ItemId, and DependsOnItemId

I conver this to a collection:

 IEnumerable<Item> items = GetItems();

each item has a: Dependencies property which is a

List<Item>

So i want to filter the initial items list to:

  1. Given a single item, i want a list of that item and all of the items that dependon this item recursively.

  2. Given a single item, i want a list of that item and all of the other items that it depends on (also recursively).

what is the best way of doing this in C#, LINQ, or anything else that would do the trick.

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

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

发布评论

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

评论(2

〆一缕阳光ご 2024-09-16 21:35:44

要获取元素的所有依赖项的列表,您可以使用以下递归函数:

IEnumerable<Item> GetAllDependencies(Item i)
{
    IEnumerable<Item> a = new Item[] { i };
    IEnumerable<Item> b = i.Dependencies
                           .SelectMany(d => GetAllDependencies(d))
                           .Distinct();
    return a.Concat(b);
}

此方法假设依赖项链中没有循环(如果存在循环,它将递归地调用自身,直到抛出 StackOverflowException )。

为了进行相反的操作,我建议构建一个新的数据结构来保存反向依赖性,然后重用相同的技术。

To get a list of all the dependencies of an element you can use the following recursive function:

IEnumerable<Item> GetAllDependencies(Item i)
{
    IEnumerable<Item> a = new Item[] { i };
    IEnumerable<Item> b = i.Dependencies
                           .SelectMany(d => GetAllDependencies(d))
                           .Distinct();
    return a.Concat(b);
}

This method assumes that there are no cycles in the dependency chain (if there is a cycle it will call itself recursively until it throws a StackOverflowException).

To do the reverse I'd suggest building a new data structure to hold the reverse-dependencies and then reuse the same technique.

你是暖光i 2024-09-16 21:35:44

这是获取所有依赖项的一种方法。

public IEnumerable<Item> GetAllDependencies(Item search)
{
    return PrivateGetAllDependencies(search, new HashSet<Item>());
}

private IEnumerable<Item> PrivateGetAllDependencies(Item search, HashSet<Item> visited)
{
    if (!visited.Contains(search))
    {
        visited.Add(search);
        foreach (Item child in search.Dependencies)
        {
            PrivateGetAllDependencies(child, visited);
        }
    }
    return visited;
}

这是获取所有反向引用的一种方法。

public IEnumerable<Item> GetAllBackReferences(Item search)
{
    return PrivateGetAllBackReferences(search, search, new HashSet<Item>(), new HashSet<Item>());
}

private IEnumerable<Item> PrivateGetAllBackReferences(Item search, Item target, HashSet<Item> visited, HashSet<Item> matched)
{
    if (!visited.Contains(search))
    {
        visited.Add(search);
        if (search == target)
        {
            matched.Add(search);
        }
        foreach (Item child in search.Dependencies)
        {
            PrivateGetAllBackReferences(child, target, visited, matched);
            if (child == target)
            {
                if (!matched.Contains(search))
                {
                    matched.Add(search);
                }
            }
        }
    }
    return matched;
}

两种算法都应该处理参考图中的循环。

Here is one way of getting all depedencies.

public IEnumerable<Item> GetAllDependencies(Item search)
{
    return PrivateGetAllDependencies(search, new HashSet<Item>());
}

private IEnumerable<Item> PrivateGetAllDependencies(Item search, HashSet<Item> visited)
{
    if (!visited.Contains(search))
    {
        visited.Add(search);
        foreach (Item child in search.Dependencies)
        {
            PrivateGetAllDependencies(child, visited);
        }
    }
    return visited;
}

And here is one way of getting all back references.

public IEnumerable<Item> GetAllBackReferences(Item search)
{
    return PrivateGetAllBackReferences(search, search, new HashSet<Item>(), new HashSet<Item>());
}

private IEnumerable<Item> PrivateGetAllBackReferences(Item search, Item target, HashSet<Item> visited, HashSet<Item> matched)
{
    if (!visited.Contains(search))
    {
        visited.Add(search);
        if (search == target)
        {
            matched.Add(search);
        }
        foreach (Item child in search.Dependencies)
        {
            PrivateGetAllBackReferences(child, target, visited, matched);
            if (child == target)
            {
                if (!matched.Contains(search))
                {
                    matched.Add(search);
                }
            }
        }
    }
    return matched;
}

Both algorithms should handle cycles in the reference graph.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文