2016-02-19 7 views
5

पुनरावृत्ति मैं दो each ब्लॉक के साथ एक नेस्टेड सरणी पर पुनरावृत्ति कर रहा हूँ, और मन की यात्रा के अंदर एक ही सरणी से एक तत्व को हटाने:हटाएं तत्व जबकि

arr = [1,2,3] 
arr.each do |x| 
    arr.each do |y| 
    puts "#{arr.delete(y)}" 
    end 
end 

यह परिणाम 1 पैदा करता है, 3। सरणी [2] बन जाती है।

मूल्य 2 क्यों पहले या दूसरे लूप को पास नहीं किया गया है? क्या यह नेस्टेड पुनरावृत्ति के दुष्प्रभाव का कुछ प्रकार है?

+0

कृपया उचित उत्तर – bronislav

+0

@bronislav को स्वीकृति दें, इसे कुछ समय दें। यह केवल एक घंटा रहा है। वहां भीड़ नहीं है। –

+0

@CarySwoveland, क्षमा करें – bronislav

उत्तर

7

यह हटाए गए तत्व की अनुक्रमणिका के कारण है। मैं तुम्हें दिखाने के लिए कुछ उत्पादन कहा:

arr = [1,2,3] 
arr.each do |x| 
    puts "1: #{arr.inspect}, x: #{x}" 
    arr.each do |y| 
    puts "2: #{arr.inspect}, y: #{y}" 
    puts "#{arr.delete(y)}" 
    end 
end 

परिणाम:

1: [1, 2, 3], x: 1 
2: [1, 2, 3], y: 1 
1 
2: [2, 3], y: 3 
3 
=> [2] 

पहले हटाया तत्व 1 है भीतरी प्रत्येक ब्लॉक में (सूचकांक 0 है)। हटाने के बाद 2 में इंडेक्स 0 है और अब प्रत्येक पुनरावृत्ति इंडेक्स 1 पर जाता है जो अब तत्व 3 है। 3 हटा दिया जाएगा और यह पुनरावृत्ति का अंत है। तो आप [2] मिलता है। बिना

एक ही होता है नेस्ट प्रत्येक:

arr = [1,2,3] 
arr.each do |x| 
    puts "1: #{arr.inspect}, x: #{x}" 
    puts "#{arr.delete(x)}" 
end 

परिणाम:

1: [1, 2, 3], x: 1 
1 
1: [2, 3], x: 3 
3 
=> [2] 

मैं ऐसे कार्यों के लिए reverse_each उपयोग करने के लिए इस व्यवहार से बचने के लिए सुझाव देते हैं:

arr = [1,2,3] 
arr.reverse_each do |x| 
    puts "1: #{arr.inspect}, x: #{x}" 
    puts "#{arr.delete(x)}" 
end 

परिणाम:

1: [1, 2, 3], x: 3 
3 
1: [1, 2], x: 2 
2 
1: [1], x: 1 
1 
=> [] 
+1

+1। या आप इन परिस्थितियों में 'चयन' या 'अस्वीकार' का उपयोग करना चुन सकते हैं – cozyconemotel

1

इस मामले को समझने के लिए, आइए इंडेक्स के साथ ट्रैवर किए जाने वाले सरल सरणी का मामला लें।

आपके पास [1,2,3] के साथ एक सरणी है।

जब आप 0 के साथ पुनरावृत्ति प्रारंभ करते हैं, तो वर्तमान तत्व 1 है। अब, आप इंडेक्स 0 पर तत्व 1 हटाते हैं, तो आपकी सरणी [2,3] बन जाएगी।

अगले पुनरावृत्ति में, आपकी अनुक्रमणिका 1 होगी और यह 3 पर इंगित होगी। और 3 हटा दिया जाएगा। आपकी सरणी [2] होगी।

अब, आपकी अनुक्रमणिका 2 है और सरणी लंबाई 1 है। तो, कुछ भी नहीं होगा। अब, जब यह आंतरिक लूप पूरा हो जाएगा, बाहरी लूप अद्यतन सूचकांक 1 और फिर 2 पर फिर से शुरू होगा। और सरणी की लंबाई 1 है, इसलिए उन्हें निष्पादित नहीं किया जाएगा।

तो, ऐसा लगता है, ऐसा लगता है कि सूचकांक पुनरावृत्ति के रूप में उपयोग कर रहा है।

मेरे ज्ञान के अनुसार, इसमें अनिर्धारित व्यवहार होना चाहिए (जैसे सी ++ में ऐसे कोड की अनुशंसा नहीं की जाती है)। चूंकि, यदि आप वर्तमान तत्व को हटाते हैं, तो यह सूचकांक को दूषित करेगा (वर्तमान में each पर फ़ंक्शन ब्लॉक के पैरामीटर में आयोजित किया जा रहा है)।

+0

आपका पहला पैराग्राफ आपकी राय/फीचर अनुरोध है, और बाकी से अलग रखा जाना चाहिए (शायद अंतराल के भीतर अंत में रखा जाना चाहिए)। मुझे लगता है कि यही कारण है कि आप संक्षिप्त उत्तर के बावजूद ऊपर नहीं जा रहे हैं।आपके पास बाहरी लूप का भी कोई उल्लेख नहीं है (कम से कम आपको यह बताने की जरूरत है कि इसका कोई प्रभाव नहीं है)। रचनात्मक सुझाव के – sawa

2

इसमें घोंसले से कोई लेना देना नहीं है।वास्तव में, तुम सिर्फ भीतरी पाश के साथ एक ही परिणाम प्राप्त होगा:

arr = [1,2,3] 
arr.each do |y| 
    puts "#{arr.delete(y)}" 
end 
# => outputs 1, 3 
a # => [2] 

compication यात्रा के दौरान सरणी को संशोधित करने के कारण है।


कारण क्योंकि Array#each सूचकांक पर आधारित है। सबसे पहले, x1 (जो परिणाम के लिए पूरी तरह से अप्रासंगिक है) बन जाता है। भीतरी पाश के भीतर, पहले तुम हो:

  • a: [1, 2, 3], index: 0, y: 1

जहां index सूचकांक जिस पर भीतरी यात्रा आधारित है, और आप y हटा सकते हैं और आपको मिलेगा:

  • a: [2, 3]
  • 012,

अगले आंतरिक यात्रा में, तुम हो:

  • a: [2, 3], index: 1, y: 3

ध्यान दें कि 2 क्योंकि यात्रा सूचकांक पर आधारित है को छोड़ दिया जाता है (1)। फिर, 3 हटा दी जाती है, जो देता है:

  • a: [2]

बाहरी पाश सूचकांक 1 पर अगले चरण का प्रयास करता है, वहाँ पर्याप्त तत्व a में नहीं बचा है, तो यह वहाँ समाप्त होता है।

0

each इंडेक्स के साथ पुनरावृत्त करता है और आप अगली पुनरावृत्ति में प्रत्येक अन्य तत्व को आंतरिक loop में एक तत्व हटा रहे हैं। यदि आप तत्वों की संख्या में वृद्धि करते हैं और लूप में पुनरावृत्ति की वर्तमान अनुक्रमणिका समेत आप बड़ी तस्वीर देख पाएंगे।

arr = [1,2,3,4,5,6,7,8,9] 
arr.each_with_index do |x,ix| 
    puts "loop1: #{arr.inspect}, x: #{x}, ix: #{ix}" 
    arr.each_with_index do |y, iy| 
    puts "loop2: #{arr.inspect}, y: #{y}, iy: #{iy}" 
    puts "#{arr.delete(y)}" 
    end 
end 

परिणाम

loop1: [1, 2, 3, 4, 5, 6, 7, 8, 9], x: 1, ix: 0 
loop2: [1, 2, 3, 4, 5, 6, 7, 8, 9], y: 1, iy: 0 
1 
loop2: [2, 3, 4, 5, 6, 7, 8, 9], y: 3, iy: 1 
3 
loop2: [2, 4, 5, 6, 7, 8, 9], y: 5, iy: 2 
5 
loop2: [2, 4, 6, 7, 8, 9], y: 7, iy: 3 
7 
loop2: [2, 4, 6, 8, 9], y: 9, iy: 4 
9 
loop1: [2, 4, 6, 8], x: 4, ix: 1 
loop2: [2, 4, 6, 8], y: 2, iy: 0 
2 
loop2: [4, 6, 8], y: 6, iy: 1 
6 
=> [4, 8] 

जब से तुम पाश के दौरान और बाद प्रत्येक सूचकांक यात्रा वृद्धि की जाती है लेकिन सरणी एक तत्व कम है हटा रहे हैं, इसलिए, यह अगले (और सभी) मिलान को हटा देता है तत्व उपलब्ध हैं और अंत में लूप तुलना करता है और लूप को रोकता है जब index >= length

संबंधित मुद्दे