LINQ中的嵌套列表到多级字典
本文关键字:多级 字典 列表 嵌套 LINQ | 更新日期: 2023-09-27 17:59:01
我有以下类
public class TreeNode
{
public string Id { get; set; }
public int Data { get; set; }
public List<TreeNode> Children { get; private set; }
public TreeNode(string node, int data)
{
Id = node;
Data = data;
Children = new List<TreeNode>();
}
public TreeNode(string node, params TreeNode[] children)
{
Id = node;
Children = new List<TreeNode>(children);
}
public override string ToString()
{
return Id;
}
}
这是一个n元树,其中只有叶节点(没有子节点)才会填充数据属性。我想使用LINQ将这个嵌套列表转换为多级字典。例如,如果树如下
TreeNode rootNode =
new TreeNode("node-0",
new TreeNode("node-1",
new TreeNode("node-2", 20)),
new TreeNode("node-3", 19),
new TreeNode("node-4",
new TreeNode("node-5", 25),
new TreeNode("node-6", 40)));
我希望使用LINQ将上述结构转换为Dictionary(注意:非平面Dictionary),如下所示。我需要作为LINQ结果的根字典。我该怎么做。请帮帮我。
Dictionary<string, object> d4 = new Dictionary<string, object>();
d4.Add("node-5", 25);
d4.Add("node-6", 40);
Dictionary<string, object> d3 = new Dictionary<string, object>();
d3.Add("node-4", d4);
Dictionary<string, object> d2 = new Dictionary<string, object>();
d2.Add("node-2", 20);
Dictionary<string, object> d1 = new Dictionary<string, object>();
d1.Add("node-1", d2);
d1.Add("node-3", 19);
d1.Add("node-4", d4);
Dictionary<string, object> root = new Dictionary<string, object>();
root.Add("node-0", d1);
更新:
由于问题不是关于扁平化层次结构,并且用户正在为给定的输入寻找层次Dictionary
,所以我对代码进行了一些修改。
public static void Main()
{
var rootNode =
new TreeNode("node-0",
new TreeNode("node-1",
new TreeNode("node-2", 20)),
new TreeNode("node-3", 19),
new TreeNode("node-4",
new TreeNode("node-5", 25),
new TreeNode("node-6", 40)));
var result = ReadHierarchy(new List<TreeNode> {rootNode});
foreach (var r in result)
{
Console.WriteLine("{0} - {1}", r.Key, r.Value);
}
Console.ReadKey();
}
private static Dictionary<string, object> ReadHierarchy(IEnumerable<TreeNode> collection)
{
return collection.ToDictionary(node => node.Id,
node => node.Children.Count > 0 ? ReadHierarchy(node.Children) : node.Data as object);
}
工作小提琴手示例
下面的解决方案使层次结构变平(如果需要,请使用)。
这里是一个简单的递归方法,它以List
为输入并返回扁平集合。。
static List<TreeNode> ReadHierarchy(List<TreeNode> collection)
{
return collection.SelectMany(c => ReadHierarchy(c.Children)).Concat(collection).ToList();
}
您可以使用简单的Linq
语句将返回的列表转换为Dictionary
。
TreeNode rootNode =
new TreeNode("node-0",
new TreeNode("node-1",
new TreeNode("node-2", 20)),
new TreeNode("node-3", 19),
new TreeNode("node-4",
new TreeNode("node-5", 25),
new TreeNode("node-6", 40)));
var result = ReadHierarchy(new List<TreeNode> {rootNode}).ToDictionary(c=>c.Id, c=>c);
工作Fiddler示例
也许在树节点本身实现getvalue逻辑会更好,但在其他情况下使用递归,以下方法应该可以做到:
Func<TreeNode, object> getvalue = null;
getvalue = tn => tn.Children.Count == 0 ? (object)tn.Data : tn.Children.ToDictionary(n => n.Id, getvalue);
var result = getvalue(rootNode) as Dictionary<string, object>;
注意,这假设根始终包含子节点,否则getvalue将返回根节点的"数据"。