我有一个包含2个表的数据库:
项目具有ID
的密钥ItemDependencies 有两列: ItemId , DependsOnItemId
我将其转换为集合:
IEnumerable<Item> items = GetItems();
每个项都有一个:依赖关系属性
List<Item>
所以我想将初始项目列表过滤到:
给定一个项目,我想要一个该项目的列表以及递归依赖此项目的所有项目。
给定一个项目,我想要一个该项目的列表以及它所依赖的所有其他项目(也是递归的)。
在C#,LINQ或其他任何可以解决这个问题的方法中,最好的方法是什么。
答案 0 :(得分:5)
要获取元素的所有依赖项列表,可以使用以下递归函数:
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
)。
为了反过来,我建议构建一个新的数据结构来保存反向依赖,然后重用相同的技术。
答案 1 :(得分:0)
这是获取所有依赖项的一种方法。
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;
}
两种算法都应该处理参考图中的循环。