2008-09-14 5 views
57

में एक पेड़ को पार करने के लिए रिकर्सिव लैम्ब्डा अभिव्यक्ति क्या कोई मुझे दिखा सकता है कि सी # में वृक्ष संरचना को पार करने के लिए एक पुनरावर्ती लैम्ब्डा अभिव्यक्ति को कैसे कार्यान्वित किया जाए।सी #

उत्तर

66

ठीक है, मुझे अंत में कुछ खाली समय मिला।
ये हम चले:

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

आईआईआरसी है फॉरएच एक्सटेंशन विधि फ्रेमवर्क में मौजूद नहीं है, इसलिए आपको इसे स्वयं लिखना होगा (जो एक आसान काम है)। – VVS

+4

@VVS यह सूची <> http://msdn.microsoft.com/en-us/library/bwabdf9z.aspx – onof

+1

में मौजूद था .... अजीब !!! – Timmerz

2

एक पौराणिक वस्तु TreeItem मानते हुए, जो आपके पदानुक्रम का प्रतिनिधित्व करने के लिए एक बच्चों का संग्रह conatins।

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

HandleTreeItems एक लैम्ब्डा नहीं है, यह सिर्फ तर्क के रूप में एक लैम्ब्डा लेता है। इस प्रकार यह विशिष्ट प्रश्न का उत्तर नहीं देता है। – Macke

23

एक उचित समाधान, और वास्तव में कई कार्यात्मक प्रोग्रामिंग भाषाओं में मुहावरेदार समाधान, एक fixed-point combinator के उपयोग होगा। संक्षेप में: एक निश्चित बिंदु संयोजक सवाल का जवाब देता है "मैं एक अज्ञात फ़ंक्शन को रिकर्सिव कैसे परिभाषित करता हूं?"। लेकिन समाधान इतना अनौपचारिक है कि पूरे लेख उन्हें समझाने के लिए लिखे गए हैं।

एक सरल, व्यावहारिक विकल्प सी के एंटीक्स में "समय पर वापस जाना" है: परिभाषा से पहले घोषणा। निम्न का प्रयास करें:

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

एक आकर्षण की तरह काम करता है।

+2

जिज्ञासा से, यह फैक्टोरियल फ़ंक्शन किस प्रश्न पर उत्तर देने में मदद कर सकता है? – aku

+7

क्योंकि यह रिकर्सिव – Guillaume86

13

सी और सी ++ की एंटीक्स में "समय पर वापस जाने" का एक आसान विकल्प है: परिभाषा से पहले घोषणा। निम्न का प्रयास करें:

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

एक आकर्षण की तरह काम करता है।

हाँ, यह एक छोटी सी चेतावनी के साथ काम करता है। सी # में परिवर्तनीय संदर्भ हैं। तो अगर आप गलती से कुछ इस तरह मत करो सुनिश्चित करें:

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 के लिंक से संयोजक का उपयोग करते हैं, तो यह संभव नहीं होगा।