C#对父/子列表进行排序,以生成平面输出
我有这个模型:C#对父/子列表进行排序,以生成平面输出,c#,algorithm,linq,parent-child,lambda,C#,Algorithm,Linq,Parent Child,Lambda,我有这个模型: public class Node { public int Id { get; set; } public string Name { get; set; } public int? ParentId { get; set; } } 我有来自数据库查询的以下数据: nodes.Add(new Node { Id = 1, Name = "Node #1", ParentId = null }); nodes.Add(n
public class Node
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
}
我有来自数据库查询的以下数据:
nodes.Add(new Node { Id = 1, Name = "Node #1", ParentId = null });
nodes.Add(new Node { Id = 2, Name = "Node #2", ParentId = 1 });
nodes.Add(new Node { Id = 3, Name = "Node #3", ParentId = 2 });
nodes.Add(new Node { Id = 4, Name = "Node #4", ParentId = null });
nodes.Add(new Node { Id = 5, Name = "Node #5", ParentId = 2 });
nodes.Add(new Node { Id = 6, Name = "Node #6", ParentId = 2 });
nodes.Add(new Node { Id = 7, Name = "Node #7", ParentId = 1 });
nodes.Add(new Node { Id = 8, Name = "Node #8", ParentId = 5 });
nodes.Add(new Node { Id = 9, Name = "Node #9", ParentId = 4 });
nodes.Add(new Node { Id = 10, Name = "Node #10", ParentId = 4 });
我想对列表进行排序并保持平面结构。我期望的结果是:
// 1 - Node #1 => NULL
// 2 - Node #2 => 1
// 3 - Node #3 => 2
// 5 - Node #5 => 2
// 8 - Node #8 => 5
// 6 - Node #6 => 2
// 7 - Node #7 => 1
// 4 - Node #4 => NULL
// 9 - Node #9 => 4
// 10 - Node #10 => 4
我指的是这个,但我没有得到我想要的结果
有什么帮助吗?您可以尝试使用
SelectMany
在LINQ中创建递归查询,如下所示:
IEnumerable<Node> Recurcive(List<Node> nodeList, int? parentId)
{
return nodeList
.Where(x => x.ParentId == parentId)
.SelectMany(x =>
new[] { new Node
{ Id = x.Id, Name = x.Name, ParentId = x.ParentId } }
.Concat(Recurcive(nodeList, x.Id)));
}
foreach (var node in Recurcive(nodes, null))
Console
.WriteLine($"Id : {node.Id}\t, Name = {node.Name}\t, Parent = {node.ParentId}");
我想你想要这个
nodes.OrderBy(n => n.ParentID ?? n.Id)
.ThenBy(n => n.Id);
我会这样做:
var nodes = new List<Node>()
{
new Node { Id = 1, Name = "Node #1", ParentId = null },
new Node { Id = 2, Name = "Node #2", ParentId = 1 },
new Node { Id = 3, Name = "Node #3", ParentId = 2 },
new Node { Id = 4, Name = "Node #4", ParentId = null },
new Node { Id = 5, Name = "Node #5", ParentId = 2 },
new Node { Id = 6, Name = "Node #6", ParentId = 2 },
new Node { Id = 7, Name = "Node #7", ParentId = 1 },
new Node { Id = 8, Name = "Node #8", ParentId = 5 },
new Node { Id = 9, Name = "Node #9", ParentId = 4 },
new Node { Id = 10, Name = "Node #10", ParentId = 4 },
};
var lookup = nodes.ToLookup(x => x.ParentId);
IEnumerable<Node> Flatten(int? parentId)
{
foreach (var node in lookup[parentId])
{
yield return node;
foreach (var child in Flatten(node.Id))
{
yield return child;
}
}
}
var output = Flatten(null).ToArray();
var节点=新列表()
{
新节点{Id=1,Name=“Node#1”,ParentId=null},
新节点{Id=2,Name=“Node#2”,ParentId=1},
新节点{Id=3,Name=“Node#3”,ParentId=2},
新节点{Id=4,Name=“Node#4”,ParentId=null},
新节点{Id=5,Name=“Node#5”,ParentId=2},
新节点{Id=6,Name=“Node#6”,ParentId=2},
新节点{Id=7,Name=“Node#7”,ParentId=1},
新节点{Id=8,Name=“Node#8”,ParentId=5},
新节点{Id=9,Name=“Node#9”,ParentId=4},
新节点{Id=10,Name=“Node#10”,ParentId=4},
};
var lookup=nodes.ToLookup(x=>x.ParentId);
IEnumerable展平(int?parentId)
{
foreach(查找[parentId]中的var节点)
{
收益回报节点;
foreach(展平中的var子节点(node.Id))
{
退换子女;
}
}
}
var输出=展平(null).ToArray();
这一点递归给了我:
为什么节点8不在末尾?@Hogan-这里真正的问题是节点7不应该出现在节点2之后。列表中的其他所有内容看起来都是深度优先搜索,除了那个节点。我想如果OP告诉我们他们到底在做什么就好了。你是对的@Hogan,我在填充output@MKR-OP的输出是深度优先和广度优先搜索的不匹配。我认为OP的输出是错误的。如果他试图进行深度优先搜索,他的节点#7应该出现在节点#6之后。@MKR-请不要这样删除您的评论。这会让你很难理解谈话内容。@MKR-我也喜欢这样。但删除评论往往会降低答案的价值。这应该避免。这就是我认为发生在这里的事情。是的,你是对的,节点#7应该出现在节点#6之后,谢谢你。我不认为
ThenBy
对OP提供的数据有任何影响。@Issam我修改过的答案应该符合你修改过的逻辑。
var nodes = new List<Node>()
{
new Node { Id = 1, Name = "Node #1", ParentId = null },
new Node { Id = 2, Name = "Node #2", ParentId = 1 },
new Node { Id = 3, Name = "Node #3", ParentId = 2 },
new Node { Id = 4, Name = "Node #4", ParentId = null },
new Node { Id = 5, Name = "Node #5", ParentId = 2 },
new Node { Id = 6, Name = "Node #6", ParentId = 2 },
new Node { Id = 7, Name = "Node #7", ParentId = 1 },
new Node { Id = 8, Name = "Node #8", ParentId = 5 },
new Node { Id = 9, Name = "Node #9", ParentId = 4 },
new Node { Id = 10, Name = "Node #10", ParentId = 4 },
};
var lookup = nodes.ToLookup(x => x.ParentId);
IEnumerable<Node> Flatten(int? parentId)
{
foreach (var node in lookup[parentId])
{
yield return node;
foreach (var child in Flatten(node.Id))
{
yield return child;
}
}
}
var output = Flatten(null).ToArray();