【问题标题】:nested list to multilevel Dictionary in LINQ嵌套列表到 LINQ 中的多级字典
【发布时间】:2015-06-23 23:18:04
【问题描述】:

我有以下课程

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 叉树,其中只有叶节点(没有子节点的节点)才会填充 data 属性。我想使用 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 将上述结构转换为字典(注意:非平面字典),如下所示。我需要根字典作为 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);

【问题讨论】:

  • 你试过什么?除了不知道如何开始之外,您的具体问题是什么?
  • Kdopen,我只能将 TreeNode 结构转换为平面字典,类似于 hari 在他的答案中发布的内容。但我无法将其转换为嵌套/多级字典。我也找不到任何类似问题的源代码示例。如果你能帮助我,那就太好了。

标签: c# .net linq


【解决方案1】:

更新:

由于问题不是关于扁平化层次结构,并且用户正在为给定的输入寻找层次结构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);
}

工作fiddler example

下面的解决方案会展平层次结构(如果需要,请使用)。

这是一个简单的递归方法,它以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 example

【讨论】:

  • hari,非常感谢您的尝试。我正在寻找的不是扁平字典,而是嵌套/多级字典。如果观察问题,字典'root'包含字典'd'1;字典“d1”包含“d2”和“d4”。字典 'd4' 包含叶节点中存在的实际数字。如何使用 LINQ 获得这种字典结构?
  • @user2079948 我提供了另一种满足您需求的解决方案。
【解决方案2】:

也许在treenode本身中实现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 将返回根节点的“数据”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 2017-08-30
    • 1970-01-01
    • 2019-02-24
    相关资源
    最近更新 更多