C#如何从父子列表中获取ID列表
我有一个包含父子关系的任务列表。关系不断变化。由于列表结构是扁平的,我需要按DisplayOrder列对每个任务进行排序 领域: 我可以想象的是,在任何关系被更改后,我以一种方式获取所有任务ID,即每个子ID位于其自己的父ID之下,然后更新这些ID在其当前序列中的显示顺序C#如何从父子列表中获取ID列表,c#,entity-framework,linq,C#,Entity Framework,Linq,我有一个包含父子关系的任务列表。关系不断变化。由于列表结构是扁平的,我需要按DisplayOrder列对每个任务进行排序 领域: 我可以想象的是,在任何关系被更改后,我以一种方式获取所有任务ID,即每个子ID位于其自己的父ID之下,然后更新这些ID在其当前序列中的显示顺序 但我不确定这在c#中是如何实现的。请就此提出建议。这看起来像是一个树状结构。 您应该安装如下内容: root | ---------------- | | A T
但我不确定这在c#中是如何实现的。请就此提出建议。这看起来像是一个树状结构。 您应该安装如下内容:
root
|
----------------
| |
A Task B Task
| |
C - A D - B
之后,您应该进行深度优先搜索以创建
显示顺序。
请点击此处:
编辑:葡萄牙语版本有一个很好的图像,有助于:
然后你会得到这个:
root (0)
|
----------------
| |
A Task (1) B Task (3)
| |
C - A (2) D - B (4)
希望这有帮助。看起来像是一个树结构。 您应该安装如下内容:
root
|
----------------
| |
A Task B Task
| |
C - A D - B
之后,您应该进行深度优先搜索以创建
显示顺序。
请点击此处:
编辑:葡萄牙语版本有一个很好的图像,有助于:
然后你会得到这个:
root (0)
|
----------------
| |
A Task (1) B Task (3)
| |
C - A (2) D - B (4)
希望这有帮助。您正在处理一个树结构,因此这需要递归 如果我理解正确,您希望以以下方式枚举任务(显然是伪代码): 因此,让我们实现递归方法:
public static class MyExtensions
{
/// <summary>
/// Traverse a hierachy of items depths-first.
/// </summary>
/// <param name="source">The item source.</param>
/// <param name="childrenGetter">Function to get the direct children of an item.</param>
/// <returns>The items in <paramref name="source"/>, each recursively followed by it's descendants.</returns>
public static IEnumerable<TSource> DepthFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> childrenGetter)
{
foreach(var item in source)
{
yield return item;
foreach (var descendant in childrenGetter(item).DepthFirst(childrenGetter))
yield return descendant;
}
}
}
现在,您可以按所需顺序枚举任务并分配DisplayOrder
:
var order = 0;
foreach (var task in childrenByParentId[null].DepthFirst(parent => childrenByParentId[parent.Id]))
task.DisplayOrder = ++order;
您正在处理一个树结构,因此这需要递归 如果我理解正确,您希望以以下方式枚举任务(显然是伪代码): 因此,让我们实现递归方法:
public static class MyExtensions
{
/// <summary>
/// Traverse a hierachy of items depths-first.
/// </summary>
/// <param name="source">The item source.</param>
/// <param name="childrenGetter">Function to get the direct children of an item.</param>
/// <returns>The items in <paramref name="source"/>, each recursively followed by it's descendants.</returns>
public static IEnumerable<TSource> DepthFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> childrenGetter)
{
foreach(var item in source)
{
yield return item;
foreach (var descendant in childrenGetter(item).DepthFirst(childrenGetter))
yield return descendant;
}
}
}
现在,您可以按所需顺序枚举任务并分配DisplayOrder
:
var order = 0;
foreach (var task in childrenByParentId[null].DepthFirst(parent => childrenByParentId[parent.Id]))
task.DisplayOrder = ++order;
请给出一些示例数据以及您想要实现的目标。现在很难理解。这是桌子的外观。任务不断添加,它们的父ID也可能会更改,所以为了在屏幕上显示一个平面列表,我添加了DisplayOrder列。现在,如果关系被更改,我还需要对排序列重新排序好,现在是您期望的示例结果。假设我改变关系,将任务C固定到A。结果应该是什么?“C-A”是“A任务”的子任务。我可以让它成为“B任务”的孩子。现在顺序应该分别是1,2,4,3。但主要的一点是,我需要所有TaskId,每个子项都必须在其父项下,请给出一些示例数据和您想要实现的目标。现在很难理解。这是桌子的外观。任务不断添加,它们的父ID也可能会更改,所以为了在屏幕上显示一个平面列表,我添加了DisplayOrder列。现在,如果关系被更改,我还需要对排序列重新排序好,现在是您期望的示例结果。假设我改变关系,将任务C固定到A。结果应该是什么?“C-A”是“A任务”的子任务。我可以让它成为“B任务”的孩子。现在顺序应该分别是1,2,4,3。但主要的一点是,我需要所有TaskId每个孩子都必须在其父ID下理论上这是我想要实现的,但我需要c#linq方法来提取TaskId的平面列表,以一种方式,所有孩子的ID都在他们的父ID下。我不认为你可以在一个linq方法中完成所有这些。不知道这是否是您的需求,但假设您有一个依赖于D-B(TaskID4)的F(TaskID5)。理论上这是我想要实现的,但我需要c#linq方法来提取TaskID的平面列表,所有子ID都在其父ID之下。我不认为用一个linq方法可以完成所有这些。不知道这是否是您的需求,但假设您有一个依赖于D-B(TaskID4)的F(TaskID5)。有没有一种方法可以将新移动项目的显示顺序放在其父项的最后?我提供的代码(感谢您接受该代码)并没有专门在任务的子项之间进行排序,也就是说,它保持了它们原来的顺序。如果您有一个排序标准(如按Id或按标题),那么可以对整个输入进行预排序,如:
var childrenByParentId=tasks.OrderBy(t=>t.Title).ToLookup(t=>t.ParentId)代码>。但是,我看不到如何在输入中检测“新移动的项目”,除非您通过该信息对其进行增强。是的,我还希望新移动的项目需要更多的信息,因为上述OrderBy方法和为新项目提供一些高显示顺序都不起作用。由于这种经验对我来说是新的,所以我依赖于实践最好的代码。很好的答案。使用.ToLookup方法的好方法。有没有一种方法可以将新移动项目的显示顺序放在其父项的最后?我提供的代码(感谢您接受该代码)并没有专门对任务的子项进行排序,也就是说,它保持了它们原来的顺序。如果您有一个排序标准(如按Id或按标题),那么可以对整个输入进行预排序,如:var childrenByParentId=tasks.OrderBy(t=>t.Title).ToLookup(t=>t.ParentId)代码>。但是,我看不到如何在输入中检测“新移动的项目”,除非您通过该信息对其进行增强。是的,我还希望新移动的项目需要更多的信息,因为上述OrderBy方法和为新项目提供一些高显示顺序都不起作用。由于这种经验对我来说是新的,所以我依赖于实践最好的代码。很好的答案。很好的使用方法。托卢库普方法。