如果在其他地方被问到这个问题,我会一直在寻找合适的答案,但是我发现的大多数信息都只允许单个子项目。
我试图编写一个在树形视图界面中显示信息的程序。我面临的问题是我从后端DB读取以下课程:
public class InputClass
{
public int id { get; set; }
public string text { get; set; }
public string icon { get; set; }
public int? parentId { get; set; }
}
我尝试将其转换为以下类型的列表:
public class OutputClass
{
public int id { get; set; }
public string text { get; set; }
public string icon { get; set; }
public List<OutputClass> children { get; set; }
}
正如您所看到的,子属性将在找到它的父项时填充。
作为示例 - 以下列表:
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
子项列表中的元素数量不应仅限于一个。有关如何正确排序的任何想法?
答案 0 :(得分:4)
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);
}
}
结果将是一个包含具有相应层次结构的输入元素的列表。
这是线性时间的解决方案,它只会循环两次项目。此外,它还支持多个级别的层次结构,因此您可以拥有父ID 5
生成第三级的项目等。
要生成输出,您可以编写这样的递归函数:
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 + " ");
}
}
对于您的输入,这会产生以下结果:
1 Item #1
4 SubItem #1
5 SubItem #2
2 Item #2
6 SubItem #3
3 Item #3
以下为例,以下输入列表使用与上述相同的转换代码生成下面的输出:
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
答案 1 :(得分:0)
以下代码应该打印出您需要的内容:
static void Main(string[] args)
{
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 });
var outputList = inputList
.Where(i => !i.parentId.HasValue) // Just get the parents
.Select(i => new OutputClass()
{
id = i.id,
icon = i.icon,
text = i.text,
children = inputList
.Where(x => x.parentId == i.id)
.Select(x => new OutputClass()
{
id = x.id,
icon = x.icon,
text = x.text,
}).ToList()
}).ToList();
foreach (var output in outputList)
{
Console.WriteLine(output.text);
output.children.ForEach(c => Console.WriteLine($"\t {c.text}"));
}
Console.ReadLine();
}
输出结果为:
Item #1
SubItem #1
SubItem #2
Item #2
SubItem #3
Item #3