2013-04-18 3 views
5

में अज्ञात आकार के स्लाइसिंग 2 डी ऐरे को संशोधित करना मुझे पता है कि इसी तरह के विषय यहां शामिल किए गए हैं, लेकिन मुझे लगता है कि मुझे लगता है कि मेरी गलतफहमी से उत्पन्न होता है कि फ़ोरैच लूप के संदर्भ में सरणी स्लाइस को कैसे विभाजित किया जाता है। मैं यह नहीं समझ सकता कि मैं गलत कहां गया हूं, इसलिए मैं कुछ अंतर्दृष्टि की तलाश में हूं।फिर पर्ल

मेरे पास पंक्तियों की एक चर संख्या के साथ 2 डी सरणी है। उदाहरण के प्रयोजनों के लिए:

@2DArray = (['str1', 1, 2, 'E', val1, val2, val3] 
      ['str2', 3, 4, 'E', val4, val5, val6] 
      ['str4', 5, 6, 'F', val7, val8, val9]) 

मैं अतिरिक्त कॉलम के साथ एक नई सरणी, निर्माण करना चाहते हैं, जो कि मूल सरणी की पंक्तियों में से कुछ को शामिल किया गया केवल अगर वे इसके अतिरिक्त स्तंभ 3. में स्ट्रिंग 'ई' को शामिल करने के लिए, पंक्तियां जो मैं अपनी नई सरणी में शामिल करना चाहता हूं, मुझे केवल कॉलम का सबसेट चाहिए और मैं उस सबसेट को एक अलग क्रम में चाहता हूं। अंतिम लक्ष्य डाउनस्ट्रीम स्क्रिप्ट द्वारा आवश्यक सही प्रारूप के आउटपुट उत्पन्न करना है।

my $projName = 'test'; 

my $i = 1; 
my @Newarray 
my @Newarray_element; 
    foreach (@2DArray) { 
     if (${$_}[3] eq 'E') { 
      ${$_}[3] = $i; 
      ${$_}[5] = '+'; 
      @Newarray_element = ("$projName$i", @$_[0,1,2,5,3], 'STR', 11, 11); 
      $i++; 
      push (@Newarray, \@Newarray_element); 
     } 

     next; 
    } 

print (join("\t", @$_), "\n") for @Newarray; 

हालांकि, अगर मैं ऐसा, मैं क्या मिलता है:

#(original) col nums:  0  1 2 5 3 

        test2 str2 3 4 + 2 STR 11 11 
        test2 str2 3 4 + 2 STR 11 11 

Ie, मेरी नई सरणी प्रत्येक पंक्ति के लिए एक पंक्ति होगा

यहाँ ऐसा करने के लिए मेरे प्रयास है कॉलम 3 में 'ई' के साथ मूल सरणी में, लेकिन प्रत्येक पंक्ति लूप द्वारा संसाधित होने वाली अंतिम पंक्ति के मानों के साथ पॉप्युलेट की जाती है।

कारण मुझे लगता है कि फोरैच लूप में 2 डी सरणी को टुकड़ा करने के साथ समस्या को हल करना है, मुझे पता है कि मैं केवल 2 डी सरणी के माध्यम से लूप करता हूं, कॉलम 3 में 'ई' के साथ सभी पंक्तियां पाता हूं, कुछ संशोधित करता हूं उन पंक्तियों के लिए अन्य कॉलम में मान, और उसके बाद इसे एक नई सरणी में वापस कर दें, यह सब पूरी तरह से काम करता है। मैं वास्तव में उत्पादन मैं उम्मीद करेंगे मिल

my @Newarray; 
my $i = 1; 
foreach (@2Darray) { 
    if (${$_}[3] eq "E") { 
     ${$_}[3] = $i; 
     ${$_}[5] = '+'; 
     $i++; 
     push (@Newarray, \@$_); 
    } 
    next; 
} 
print (join("\t", @$_), "\n") for @Newarray; 

:

    *   & 
str1 1 2 1 val1 + val3 
str2 3 4 2 val4 + val6 

जहां स्तंभों के आधार पर * और & चिह्नित संशोधित कॉलम 3 और 5 हैं कि, कहने के लिए है, तो मैं इसके बजाय यह करने के लिए है। हमले की शुरुआत करें: मेरी नौसिखिया स्वयं गलत कहां गई?

उत्तर

4

परिवर्तनीय @Newarray_element आपके पूरे कार्यक्रम में एक ही मेमोरी स्पेस को इंगित करता है, इसलिए एक पुनरावृत्ति में आपके द्वारा किए गए परिवर्तन पिछले पुनरावृत्तियों में प्रचारित होते हैं जहां आपने असाइनमेंट में उस चर का उपयोग किया था।

दो संभावित समाधान:

एक। चर के दायरे को बदलें ताकि यह प्रत्येक पुनरावृत्ति में विभिन्न स्मृति का उपयोग करे। बदलें

my @Newarray_element; 
foreach (@2DArray) { 
    ... 

को
foreach (@2DArray) { 
    my @Newarray_element; 
    ... 

या यहाँ तक कि

foreach (@2DArray) { 
    ... 
    my @Newarray_element = ("$projName$i", @$_[0,1,2,5,3], 'STR', 11, 11); 

दो: @Newarray_element पुन: उपयोग लेकिन @Newarray की प्रत्येक पंक्ति के लिए अपने डेटा की एक प्रतिलिपि आवंटित।बदले

push (@Newarray, \@Newarray_element); 

को
push (@Newarray, [ @Newarray_element ]); 

यह बाद कॉल बनाता है और @Newarray के लिए एक नया, अनाम सरणी संदर्भ जोड़ देता है।

+0

धन्यवाद। एक बहुत ही गूढ़ गलती, और सबूत है कि मैंने अभी तक पर्ल संदर्भों को महारत हासिल नहीं किया है। क्या आप मुझे अपने दूसरे उदाहरण में समझा सकते हैं, बिल्कुल [@New_element] क्या कर रहा है? अगर मैं इसे सही तरीके से पढ़ रहा हूं, तो क्या यह लूप बंद होने पर @Newarray_element की सामग्री के साथ एक अनाम सरणी बनाता है? – MCor

+1

@MCor: हां, '[@Newarray_element]' '@ Newarray_element' की सामग्री की एक अनाम प्रतिलिपि बनाता है (और उस प्रति का संदर्भ देता है), ताकि जब आप लूप के अगले पुनरावृत्ति पर' @ Newarray_element' को ओवरराइट करते हैं , प्रतिलिपि अभी भी मूल सामग्री को बनाए रखेगी। (हालांकि, यह आईओओ लूप के अंदर 'मेरी' घोषणा को स्थानांतरित करके प्रत्येक पुनरावृत्ति पर एक नया स्थानीय सरणी बनाने के लिए बहुत साफ होगा।) –

+1

'[...] 'एक नया अनाम सरणी संदर्भ बनाता है, जिसे धक्का दिया जाएगा '@ न्यूएरे 'पर। उस संदर्भ द्वारा इंगित सरणी की सामग्री '@ Newarray_element' में सामग्री की एक प्रति होगी। चूंकि प्रत्येक एक प्रतिलिपि है, इससे कोई फर्क नहीं पड़ता कि आप लूप के माध्यम से हर बार '@ Newarray_element' बदलते हैं। लेकिन @ भीड़ का पहला सुझाव यह करने के लिए बहुत स्पष्ट और अधिक मूर्ख तरीका है। लूप के अंदर वैरिएबल को स्कॉप करने से प्रत्येक बार * नया * '\ @ Newarray_element' बनाता है। – friedo