2012-05-21 10 views
5

रूबी में आमतौर पर जो चीजें मिलती हैं उनमें से एक रिकर्स पैटर्न है। उदाहरण के लिए, मान लें कि मेरे पास एक सरणी है, और इसमें असीमित गहराई के तत्वों के रूप में सरणी हो सकती है। तो, उदाहरण के लिए:रूबी: मानक रिकर्सन पैटर्न

my_array = [1, [2, 3, [4, 5, [6, 7]]]] 

मैं एक तरीका है जिसके [1, 2, 3, 4, 5, 6, 7] में सरणी समतल कर सकते हैं बनाना चाहते हैं।

मुझे पता है कि .flatten नौकरी करेगा, लेकिन यह समस्या नियमित रूप से चलने वाले रिकर्सन मुद्दों का एक उदाहरण है - और इस तरह मैं एक और पुन: प्रयोज्य समाधान खोजने की कोशिश कर रहा हूं।

संक्षेप में - मुझे लगता है कि इस तरह की चीज़ के लिए एक मानक पैटर्न है, लेकिन मैं विशेष रूप से सुरुचिपूर्ण कुछ भी नहीं कर सकता। कोई भी विचार की सराहना की

उत्तर

5

रिकर्सन एक विधि है, यह भाषा पर निर्भर नहीं है। आप दो प्रकार के मामलों के साथ एल्गोरिदम लिखते हैं: वे लोग जो फ़ंक्शन को फिर से कॉल करते हैं (रिकर्सन केस) और जो इसे तोड़ते हैं (मूल मामले)। उदाहरण के लिए, रूबी में एक पुनरावर्ती समतल करने के लिए:

class Array 
    def deep_flatten 
    flat_map do |item| 
     if item.is_a?(Array) 
     item.deep_flatten 
     else 
     [item] 
     end 
    end 
    end 
end 

[[[1]], [2, 3], [4, 5, [[6]], 7]].deep_flatten 
#=> [1, 2, 3, 4, 5, 6, 7] 

इस मदद करता है? वैसे भी, यहां दिखाया गया एक उपयोगी पैटर्न यह है कि जब आप सरणी पर भर्ती का उपयोग कर रहे हैं, तो आपको आमतौर पर flat_map (each + concat/push के कार्यात्मक विकल्प) की आवश्यकता होती है।

+0

प्रतिक्रिया के लिए धन्यवाद। मैं मूल रूप से एक वर्ग के बाहर एक समारोह के साथ कोशिश कर रहा था, जो रिकर्सिवली आइटम item.my_flatten को कॉल नहीं करेगा ... लेकिन यह काम करता है। चीयर्स – PlankTon

+1

@PlankTon। फ़ंक्शन के रूप में my_flatten को लिखने के लिए ऊपर दिए गए कोड पर कुछ मामूली परिवर्तन की आवश्यकता है। लेकिन एक ओओपी भाषा होने के नाते, और 'my_flatten' एक सामान्य एल्गोरिदम है, यह इसे ऐरे में जोड़ने के लिए समझ में आता है। – tokland

4

ठीक है, अगर तुम सी का एक सा पता है, तो आप सिर्फ डॉक्स पर जाएँ और गहरे लाल रंग का समारोह क्लिक सी स्रोत प्राप्त करने के लिए करने के लिए है और यह सब है ..

http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-flatten 

और के लिए इस मामले में, यहां एक रूबी कार्यान्वयन

def flatten values, level=-1 
    flat = [] 
    values.each do |value| 
    if level != 0 && value.kind_of?(Array) 
     flat.concat(flatten(value, level-1)) 
    else 
     flat << value 
    end 
    end 
    flat 
end 

p flatten [1, [2, 3, [4, 5, [6, 7]]]] 
#=> [1, 2, 3, 4, 5, 6, 7] 
+0

आह - concat। मैं फिर से फ़ंक्शन को कॉल करने की कोशिश कर रहा था, लेकिन वह ऐसा करेगा। चीयर्स – PlankTon

2

यहां एक पूंछ रिकर्सिव शैली में लिखा गया एक फ़्लैटन का एक उदाहरण है।

class Array 

    # Monkeypatching the flatten class 
    def flatten(new_arr = []) 
    self.each do |el| 
     if el.is_a?(Array) 
     el.flatten(new_arr) 
     else 
     new_arr << el 
     end 
    end 

    new_arr 
    end 
end 

p flatten [1, [2, 3, [4, 5, [6, 7]]]] 
#=> [1, 2, 3, 4, 5, 6, 7] 

हालांकि यह की तरह गहरे लाल रंग का हमेशा पूंछ प्रत्यावर्तन के लिए अनुकूल नहीं है दिखता है: Does ruby perform tail call optimization?