سؤال

هل يمكن لأي شخص أن يوضح لي كيفية تنفيذ تعبير لامدا العودي لاجتياز بنية شجرة في C#.

هل كانت مفيدة؟

المحلول

حسنًا، لقد وجدت بعض وقت الفراغ أخيرًا.
ها نحن:

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);

نصائح أخرى

الحل المناسب، بل والحل الاصطلاحي في العديد من لغات البرمجة الوظيفية، سيكون استخدام ملف مجمع النقطة الثابتة.شيء صغير:يجيب مُجمع النقاط الثابتة على السؤال "كيف يمكنني تحديد وظيفة مجهولة لتكون متكررة؟".لكن الحل ليس تافهًا لدرجة أنه تمت كتابة مقالات كاملة لشرحه.

البديل البسيط والعملي هو "العودة بالزمن" إلى تصرفات لغة C:التصريح قبل التعريف.جرب ما يلي (الوظيفة "المضروب"):

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

يعمل كالسحر.

أو، لاجتياز شجرة الطلب المسبق على كائن من الفئة TreeNode الذي ينفذ IEnumerable<TreeNode> بشكل مناسب للذهاب على أطفالها:

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

بالطبع، هذا المثال مفتعل بعض الشيء، ولكن يمكن أن يحدث هذا عند استخدام مراجع قابلة للتغيير.إذا كنت تستخدم combinators من akuالروابط، وهذا لن يكون ممكنا.

بافتراض وجود كائن أسطوري TreeItem، يحتوي على مجموعة الأطفال لتمثيل التسلسل الهرمي الخاص بك.

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

        item(parent);
    }

الآن نسميها، ونمرر لامدا التي تتعامل مع عنصر واحد، عن طريق طباعة اسمه على وحدة التحكم.

HandleTreeItems(item => { Console.WriteLine(item.Name); }, TreeItemRoot);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top