簡體   English   中英

遞歸 lambda 表達式遍歷 C# 中的樹

[英]Recursive lambda expression to traverse a tree in C#

有人可以告訴我如何實現遞歸 lambda 表達式來遍歷 C# 中的樹結構。

好的,我終於找到了一些空閑時間。
這里我們 go:

class TreeNode
{
    public string Value { get; set;}
    public List<TreeNode> Nodes { get; set;}


    public TreeNode()
    {
        Nodes = new List<TreeNode>();
    }
}

Action<TreeNode> traverse = null;

traverse = (n) => { Console.WriteLine(n.Value); n.Nodes.ForEach(traverse);};

var root = new TreeNode { Value = "Root" };
root.Nodes.Add(new TreeNode { Value = "ChildA"} );
root.Nodes[0].Nodes.Add(new TreeNode { Value = "ChildA1" });
root.Nodes[0].Nodes.Add(new TreeNode { Value = "ChildA2" });
root.Nodes.Add(new TreeNode { Value = "ChildB"} );
root.Nodes[1].Nodes.Add(new TreeNode { Value = "ChildB1" });
root.Nodes[1].Nodes.Add(new TreeNode { Value = "ChildB2" });

traverse(root);

一個合適的解決方案,實際上是許多函數式編程語言中的慣用解決方案,將是使用定點組合器 簡而言之:定點組合器回答了“我如何將匿名 function 定義為遞歸的?”的問題。 但是解決方案是如此重要,以至於寫了整篇文章來解釋它們。

一個簡單、實用的替代方案是“回到過去”到 C 的滑稽動作:定義前聲明。 嘗試以下(“階乘”函數):

Func<int, int> fact = null;
fact = x => (x == 0) ? 1 : x * fact(x - 1);

奇跡般有效。

或者,對於 class TreeNode的 object 上的預排序樹遍歷,它在其子節點上適當地實現IEnumerable<TreeNode>到 go:

Action<TreeNode, Action<TreeNode>> preorderTraverse = null;
preorderTraverse = (node, action) => {
    action(node);
    foreach (var child in node) preorderTraverse(child, action);
};

一個簡單的替代方法是“回到過去”到 C 和 C++ 的滑稽動作:定義前聲明。 嘗試以下操作:

 Func<int, int> fact = null; fact = x => (x == 0)? 1: x * fact(x - 1);

奇跡般有效。

是的,這確實有效,但有一點需要注意。 C# 具有可變引用。 因此,請確保您不會意外地執行以下操作:

Func<int, int> fact = null;
fact = x => (x == 0) ? 1 : x * fact(x - 1);

// Make a new reference to the factorial function
Func<int, int> myFact = fact;

// Use the new reference to calculate the factorial of 4
myFact(4); // returns 24

// Modify the old reference
fact = x => x;

// Again, use the new reference to calculate
myFact(4); // returns 12

當然,這個例子有點做作,但是在使用可變引用時可能會發生這種情況。 如果您使用來自aku鏈接的組合器,這是不可能的。

假設一個神話般的 object TreeItem,它包含一個 Children 集合來表示您的層次結構。

    public void HandleTreeItems(Action<TreeItem> item, TreeItem parent)
    {
        if (parent.Children.Count > 0)
        {
            foreach (TreeItem ti in parent.Children)
            {
                HandleTreeItems(item, ti);
            }
        }

        item(parent);
    }

現在調用它,通過將其名稱打印到控制台來傳遞處理一項的 lambda。

HandleTreeItems(item => { Console.WriteLine(item.Name); }, TreeItemRoot);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM