带有子项的订购清单 [英] Ordering List with Child Items
问题描述
很抱歉,如果在其他地方询问此问题,但是我一直在寻找合适的答案,但是我发现的大多数信息仅允许单个子项.
Apologies if this is asked elsewhere however I have searched around for a suitable answer, however most of the information I have found allows for single child item only.
我正在尝试编写一个在树形视图风格的界面中显示信息的程序.我面临的问题是我正在从后端数据库中读取以下类:
I'm trying to write a program that displays information in a treeview style interface. The problem I'm facing is that I'm reading the following class from my backend DB:
public class InputClass
{
public int id { get; set; }
public string text { get; set; }
public string icon { get; set; }
public int? parentId { get; set; }
}
,我正在尝试将其转换为以下类型的列表:
and I'm trying to convert it to a list of the following type:
public class OutputClass
{
public int id { get; set; }
public string text { get; set; }
public string icon { get; set; }
public List<OutputClass> children { get; set; }
}
如您所见,children属性将在找到其父项时填充.
as you can see, the children property will populate when it finds it's parent item.
作为示例-以下列表:
var inputList = new List<InputClass>();
inputList.Add(new InputClass() { id = 1, text = "Item #1"});
inputList.Add(new InputClass() { id = 2, text = "Item #2" });
inputList.Add(new InputClass() { id = 3, text = "Item #3" });
inputList.Add(new InputClass() { id = 4, text = "SubItem #1", parentId = 1 });
inputList.Add(new InputClass() { id = 5, text = "SubItem #2", parentId = 1 });
inputList.Add(new InputClass() { id = 6, text = "SubItem #3", parentId = 2 });
应输出为:
Item #1
----SubItem #1
----SubItem #2
Item #2
----SubItem #3
Item #3
子级列表中的元素数量不应仅限于一个.关于如何正确排序的任何想法?
the number of elements in the children list should not be limited to just one. Any ideas on how to sort this properly?
推荐答案
var mapping = inputList
// for each input element, capture the parent id and create the respective output object
.Select(input => new {
ParentId = input.parentId,
Obj = new OutputClass() { id = input.id, text = input.text, icon = input.icon, children = new List<OutputClass>() }
})
// create a dictionary so we can look up the elements by id
.ToDictionary(x => x.Obj.id);
// create target list
List<OutputClass> output = new List<OutputClass>();
// loop through all elements
foreach (var x in mapping.Values)
{
// if the element has a parent id
if (x.ParentId.HasValue)
{
// find the parent object …
OutputClass parentObj = mapping[x.ParentId.Value].Obj;
// … and add this object to the parent’s child list
parentObj.children.Add(x.Obj);
}
else
{
// otherwise this is a root element, so add it to the target list
output.Add(x.Obj);
}
}
结果将是一个列表,其中包含具有各自层次结构的输入元素.
The result will be a list that contains the input elements with the respective hiearchy.
这是线性时间的解决方案,它只循环两次.此外,它还支持多个级别的层次结构,因此您可以使具有父ID 5
的项目生成第三级,等等.
This is a solution in linear time, and it only loops through the items twice. Furthermore, it also supports hierarchies of multiple levels, so you could have items that have a parent id 5
producing a third level, etc.
要产生输出,可以编写一个如下的递归函数:
To produce the output, you could write a recursive function like this:
public static void Print(IEnumerable<OutputClass> elements, string indent="")
{
foreach (OutputClass element in elements)
{
Console.WriteLine("{0}{1} {2}", indent, element.id, element.text);
Print(element.children, indent + " ");
}
}
对于您的输入,这将产生以下结果:
For your input, this produces the following result:
1 Item #1
4 SubItem #1
5 SubItem #2
2 Item #2
6 SubItem #3
3 Item #3
作为示例,以下输入列表使用与上面相同的转换代码生成下面的输出:
And just as an example, the following input list produces the output below, using the same conversion code as above:
var inputList = new List<InputClass>()
{
new InputClass() { id = 1, text = "Item 1" },
new InputClass() { id = 2, text = "Item 2" },
new InputClass() { id = 3, text = "Item 3" },
new InputClass() { id = 4, text = "SubItem 1.1", parentId = 1 },
new InputClass() { id = 5, text = "SubItem 1.2", parentId = 1 },
new InputClass() { id = 6, text = "SubItem 2.1", parentId = 2 },
new InputClass() { id = 7, text = "SubItem 2.2", parentId = 2 },
new InputClass() { id = 8, text = "SubItem 1.2.1", parentId = 5 },
new InputClass() { id = 9, text = "SubItem 1.2.2", parentId = 5 },
new InputClass() { id = 10, text = "SubItem 1.2.1.1", parentId = 8 },
new InputClass() { id = 11, text = "SubItem 2.1.1", parentId = 6 },
new InputClass() { id = 12, text = "SubItem 2.1.1.1", parentId = 11 },
new InputClass() { id = 13, text = "SubItem 2.1.1.1.1", parentId = 12 },
new InputClass() { id = 14, text = "SubItem 2.1.1.1.2", parentId = 12 }
};
输出:
1 Item 1
4 SubItem 1.1
5 SubItem 1.2
8 SubItem 1.2.1
10 SubItem 1.2.1.1
9 SubItem 1.2.2
2 Item 2
6 SubItem 2.1
11 SubItem 2.1.1
12 SubItem 2.1.1.1
13 SubItem 2.1.1.1.1
14 SubItem 2.1.1.1.2
7 SubItem 2.2
3 Item 3
这篇关于带有子项的订购清单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!