我在c#中有一个类对象列表。类具有以下属性:
int id;
int parentId;
id 是当前对象的id,parentId是parent的id。
现在我在列表中有超过100个对象。 我想解析这些对象并以格式(如树结构)生成结果
第一名 - 第二名 - 第三名 - 第四名
其中每个都是级别
例如:如果我们有8个对象{1,0},{2,1},{3,1},{4,3},{5,3},{6,2},{7, 1},{8,4} 结果应该是:
第一名 - 第二名 - 第三名 - 第四名
1 - - -
1 2 - -
1 2 6 -
1 3 - -
1 3 5 -
1 3 4 -
1 3 4 8
1 7 - -
目前我正在做的是使用4 for loops
as,
@for(var item in Model ){
for(var second in Model ){
if(second.parentId == item.id){
//add to table
}
for(var third in Model ){
if(third .parentId == item.id){
//add to table
}
for(var fourth in Model ){
if(fourth .parentId == item.id){
//add to table
}
}
}
}
}
这里的事情可以正常工作,但由于我在列表中有100多个对象(n ^ 4的复杂性),因此需要花费太多时间来解析。
有没有其他方法可以达到同样的目的?
答案 0 :(得分:1)
有必要以允许有效访问父ID的子ID的方式排列数据。这可以通过扫描输入列表并将结果存储到从parentID映射到子ID列表的字典中以恒定时间完成。方便的是,Linq提供了.ToLookup扩展方法,它几乎可以做到这一点,并且大概是O(N)的成本。
可以提供根节点,也可以在恒定时间内扫描根节点。 (实际上可能有不止一个。就此而言,数据可能包含循环)。
然后递归地遍历树,如果没有循环,可以在O(N)时间内完成。
示例代码:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
class Link
{
public int id;
public int parentId;
}
static List<Link> GetInput()
{
var data = new Dictionary<int, int> {{1,0},{2,1},{3,1},{4,3},{5,3},{6,2},{7,1},{8,4}};
return data.Select(pair => new Link { id = pair.Key, parentId = pair.Value }).ToList();
}
public static void Main()
{
List<Link> inputData = GetInput();
// Scan the nodes and arrange as a lookup (dictionary that maps from parentId to child ids)
ILookup<int, int> nodes = inputData.ToLookup( link => link.parentId, link => link.id );
// Find root node(s)
// (ints that appear as parent IDs, but as child id)
IEnumerable<int> roots = inputData
.Select( link => link.parentId)
.Except( inputData.Select( link => link.id ) );
foreach (int rootId in roots)
{
Display(rootId, nodes, "", 3);
}
}
static void Display(int id, ILookup<int, int> nodes, string prefix, int padding)
{
// Write node to console
Console.Write(prefix);
Console.Write(id);
for (int i=0; i<padding; i++)
{
Console.Write(" --");
}
Console.WriteLine();
// Recursively write children to console
string newPrefix = prefix + id.ToString() + " ";
foreach (int childId in nodes[id])
{
Display( childId, nodes, newPrefix, padding-1 );
}
}
}
可能有很多事情可以改进,但它会完成这项工作。