【问题标题】:What is the best way to find all dependent children in a IEnumerable collection在 IEnumerable 集合中查找所有依赖子项的最佳方法是什么
【发布时间】:2010-07-17 17:19:04
【问题描述】:

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

  1. 项目
  2. 项目依赖项

物品有 ID 的键

ItemDependencies 有两列:ItemIdDependsOnItemId

我把它转换成一个集合:

 IEnumerable<Item> items = GetItems();

每个 item 都有一个:Dependencies 属性,它是一个

List<Item>

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

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

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

在 C#、LINQ 或其他任何可以解决问题的方法中,最好的方法是什么。

【问题讨论】:

  • 假设依赖链中没有循环是否安全?
  • 每个项目是否显示为仅对另一个项目的直接依赖,或者多个项目可以对同一个项目有依赖关系?即这是一个传统的“树结构”,每个项目在树中只出现一次?

标签: c# linq collections ienumerable


【解决方案1】:

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

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)。

相反,我建议构建一个新的数据结构来保存反向依赖关系,然后重用相同的技术。

【讨论】:

  • 非常有用的一个。非常感谢你。
【解决方案2】:

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

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;
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-11
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多